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) */