LCOV - code coverage report
Current view: top level - lib/process - daemon.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 50 0.0 %
Date: 2021-11-24 03:28:48 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /* Copyright (c) 2003, Roger Dingledine
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : /**
       7             :  * \file daemon.c
       8             :  * \brief Run the tor process in the background (unix only)
       9             :  **/
      10             : 
      11             : #include "orconfig.h"
      12             : #include "lib/process/daemon.h"
      13             : 
      14             : #ifndef _WIN32
      15             : 
      16             : #include "lib/fs/files.h"
      17             : #include "lib/log/log.h"
      18             : #include "lib/thread/threads.h"
      19             : 
      20             : #ifdef HAVE_SYS_TYPES_H
      21             : #include <sys/types.h>
      22             : #endif
      23             : #ifdef HAVE_UNISTD_H
      24             : #include <unistd.h>
      25             : #endif
      26             : #ifdef HAVE_FCNTL_H
      27             : #include <fcntl.h>
      28             : #endif
      29             : #include <errno.h>
      30             : #include <stdlib.h>
      31             : #include <string.h>
      32             : 
      33             : /* Based on code contributed by christian grothoff */
      34             : /** True iff we've called start_daemon(). */
      35             : static int start_daemon_called = 0;
      36             : /** True iff we've called finish_daemon(). */
      37             : static int finish_daemon_called = 0;
      38             : /** Socketpair used to communicate between parent and child process while
      39             :  * daemonizing. */
      40             : static int daemon_filedes[2];
      41             : 
      42             : /**
      43             :  * Return true iff we've called start_daemon() at least once.
      44             :  */
      45             : bool
      46           0 : start_daemon_has_been_called(void)
      47             : {
      48           0 :   return start_daemon_called != 0;
      49             : }
      50             : 
      51             : /** Start putting the process into daemon mode: fork and drop all resources
      52             :  * except standard fds.  The parent process never returns, but stays around
      53             :  * until finish_daemon is called.  (Note: it's safe to call this more
      54             :  * than once: calls after the first are ignored.)  Return true if we actually
      55             :  * forked and this is the child; false otherwise.
      56             :  */
      57             : int
      58           0 : start_daemon(void)
      59             : {
      60           0 :   pid_t pid;
      61             : 
      62           0 :   if (start_daemon_called)
      63             :     return 0;
      64           0 :   start_daemon_called = 1;
      65             : 
      66           0 :   if (pipe(daemon_filedes)) {
      67             :     /* LCOV_EXCL_START */
      68             :     log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno));
      69             :     exit(1); // exit ok: during daemonize, pipe failed.
      70             :     /* LCOV_EXCL_STOP */
      71             :   }
      72           0 :   pid = fork();
      73           0 :   if (pid < 0) {
      74             :     /* LCOV_EXCL_START */
      75             :     log_err(LD_GENERAL,"fork failed. Exiting.");
      76             :     exit(1); // exit ok: during daemonize, fork failed
      77             :     /* LCOV_EXCL_STOP */
      78             :   }
      79           0 :   if (pid) {  /* Parent */
      80           0 :     int ok;
      81           0 :     char c;
      82             : 
      83           0 :     close(daemon_filedes[1]); /* we only read */
      84           0 :     ok = -1;
      85           0 :     while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
      86           0 :       if (c == '.')
      87           0 :         ok = 1;
      88             :     }
      89           0 :     fflush(stdout);
      90           0 :     if (ok == 1)
      91           0 :       exit(0); // exit ok: during daemonize, daemonizing.
      92             :     else
      93           0 :       exit(1); /* child reported error. exit ok: daemonize failed. */
      94             :     return 0; // LCOV_EXCL_LINE unreachable
      95             :   } else { /* Child */
      96           0 :     close(daemon_filedes[0]); /* we only write */
      97             : 
      98           0 :     (void) setsid(); /* Detach from controlling terminal */
      99             :     /*
     100             :      * Fork one more time, so the parent (the session group leader) can exit.
     101             :      * This means that we, as a non-session group leader, can never regain a
     102             :      * controlling terminal.   This part is recommended by Stevens's
     103             :      * _Advanced Programming in the Unix Environment_.
     104             :      */
     105           0 :     if (fork() != 0) {
     106           0 :       exit(0); // exit ok: during daemonize, fork failed (2)
     107             :     }
     108           0 :     set_main_thread(); /* We are now the main thread. */
     109             : 
     110           0 :     return 1;
     111             :   }
     112             : }
     113             : 
     114             : /** Finish putting the process into daemon mode: drop standard fds, and tell
     115             :  * the parent process to exit.  (Note: it's safe to call this more than once:
     116             :  * calls after the first are ignored.  Calls start_daemon first if it hasn't
     117             :  * been called already.) Return true if we actually did a fork; false if we
     118             :  * didn't.
     119             :  */
     120             : int
     121           0 : finish_daemon(const char *desired_cwd)
     122             : {
     123           0 :   int nullfd;
     124           0 :   char c = '.';
     125           0 :   if (finish_daemon_called)
     126             :     return 0;
     127           0 :   if (!start_daemon_called)
     128           0 :     start_daemon();
     129           0 :   finish_daemon_called = 1;
     130             : 
     131           0 :   if (!desired_cwd)
     132           0 :     desired_cwd = "/";
     133             :    /* Don't hold the wrong FS mounted */
     134           0 :   if (chdir(desired_cwd) < 0) {
     135           0 :     log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd);
     136           0 :     exit(1); // exit ok: during daemonize, chdir failed.
     137             :   }
     138             : 
     139           0 :   nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
     140           0 :   if (nullfd < 0) {
     141             :     /* LCOV_EXCL_START */
     142             :     log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
     143             :     exit(1); // exit ok: during daemonize, couldn't open /dev/null
     144             :     /* LCOV_EXCL_STOP */
     145             :   }
     146             :   /* close fds linking to invoking terminal, but
     147             :    * close usual incoming fds, but redirect them somewhere
     148             :    * useful so the fds don't get reallocated elsewhere.
     149             :    */
     150           0 :   if (dup2(nullfd,0) < 0 ||
     151           0 :       dup2(nullfd,1) < 0 ||
     152           0 :       dup2(nullfd,2) < 0) {
     153             :     /* LCOV_EXCL_START */
     154             :     log_err(LD_GENERAL,"dup2 failed. Exiting.");
     155             :     exit(1); // exit ok: during daemonize, dup2 failed.
     156             :     /* LCOV_EXCL_STOP */
     157             :   }
     158           0 :   if (nullfd > 2)
     159           0 :     close(nullfd);
     160             :   /* signal success */
     161           0 :   if (write(daemon_filedes[1], &c, sizeof(char)) != sizeof(char)) {
     162           0 :     log_err(LD_GENERAL,"write failed. Exiting.");
     163             :   }
     164           0 :   close(daemon_filedes[1]);
     165             : 
     166           0 :   return 0;
     167             : }
     168             : #else /* defined(_WIN32) */
     169             : /* defined(_WIN32) */
     170             : int
     171             : start_daemon(void)
     172             : {
     173             :   return 0;
     174             : }
     175             : int
     176             : finish_daemon(const char *cp)
     177             : {
     178             :   (void)cp;
     179             :   return 0;
     180             : }
     181             : bool
     182             : start_daemon_has_been_called(void)
     183             : {
     184             :   return false;
     185             : }
     186             : 
     187             : #endif /* !defined(_WIN32) */

Generated by: LCOV version 1.14