tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

daemon.c (4993B)


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