/src/tor/src/lib/process/daemon.c
Line | Count | Source |
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 | 0 | { |
49 | 0 | return start_daemon_called != 0; |
50 | 0 | } |
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 | 0 | { |
61 | 0 | pid_t pid; |
62 | |
|
63 | 0 | if (start_daemon_called) |
64 | 0 | return 0; |
65 | 0 | start_daemon_called = 1; |
66 | |
|
67 | 0 | if (tor_pipe_cloexec(daemon_filedes)) { |
68 | | /* LCOV_EXCL_START */ |
69 | 0 | log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno)); |
70 | 0 | exit(1); // exit ok: during daemonize, pipe failed. |
71 | | /* LCOV_EXCL_STOP */ |
72 | 0 | } |
73 | 0 | pid = fork(); |
74 | 0 | if (pid < 0) { |
75 | | /* LCOV_EXCL_START */ |
76 | 0 | log_err(LD_GENERAL,"fork failed. Exiting."); |
77 | 0 | exit(1); // exit ok: during daemonize, fork failed |
78 | | /* LCOV_EXCL_STOP */ |
79 | 0 | } |
80 | 0 | if (pid) { /* Parent */ |
81 | 0 | int ok; |
82 | 0 | char c; |
83 | |
|
84 | 0 | close(daemon_filedes[1]); /* we only read */ |
85 | 0 | ok = -1; |
86 | 0 | while (0 < read(daemon_filedes[0], &c, sizeof(char))) { |
87 | 0 | if (c == '.') |
88 | 0 | ok = 1; |
89 | 0 | } |
90 | 0 | fflush(stdout); |
91 | 0 | if (ok == 1) |
92 | 0 | exit(0); // exit ok: during daemonize, daemonizing. |
93 | 0 | else |
94 | 0 | exit(1); /* child reported error. exit ok: daemonize failed. */ |
95 | 0 | return 0; // LCOV_EXCL_LINE unreachable |
96 | 0 | } else { /* Child */ |
97 | 0 | close(daemon_filedes[0]); /* we only write */ |
98 | |
|
99 | 0 | (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 | 0 | if (fork() != 0) { |
107 | 0 | exit(0); // exit ok: during daemonize, fork failed (2) |
108 | 0 | } |
109 | 0 | set_main_thread(); /* We are now the main thread. */ |
110 | |
|
111 | 0 | return 1; |
112 | 0 | } |
113 | 0 | } |
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 | 0 | { |
124 | 0 | int nullfd; |
125 | 0 | char c = '.'; |
126 | 0 | if (finish_daemon_called) |
127 | 0 | return 0; |
128 | 0 | if (!start_daemon_called) |
129 | 0 | start_daemon(); |
130 | 0 | finish_daemon_called = 1; |
131 | |
|
132 | 0 | if (!desired_cwd) |
133 | 0 | desired_cwd = "/"; |
134 | | /* Don't hold the wrong FS mounted */ |
135 | 0 | if (chdir(desired_cwd) < 0) { |
136 | 0 | log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd); |
137 | 0 | exit(1); // exit ok: during daemonize, chdir failed. |
138 | 0 | } |
139 | | |
140 | 0 | nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0); |
141 | 0 | if (nullfd < 0) { |
142 | | /* LCOV_EXCL_START */ |
143 | 0 | log_err(LD_GENERAL,"/dev/null can't be opened. Exiting."); |
144 | 0 | exit(1); // exit ok: during daemonize, couldn't open /dev/null |
145 | | /* LCOV_EXCL_STOP */ |
146 | 0 | } |
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 | 0 | if (dup2(nullfd,0) < 0 || |
152 | 0 | dup2(nullfd,1) < 0 || |
153 | 0 | dup2(nullfd,2) < 0) { |
154 | | /* LCOV_EXCL_START */ |
155 | 0 | log_err(LD_GENERAL,"dup2 failed. Exiting."); |
156 | 0 | exit(1); // exit ok: during daemonize, dup2 failed. |
157 | | /* LCOV_EXCL_STOP */ |
158 | 0 | } |
159 | 0 | if (nullfd > 2) |
160 | 0 | close(nullfd); |
161 | | /* signal success */ |
162 | 0 | if (write(daemon_filedes[1], &c, sizeof(char)) != sizeof(char)) { |
163 | 0 | log_err(LD_GENERAL,"write failed. Exiting."); |
164 | 0 | } |
165 | 0 | close(daemon_filedes[1]); |
166 | |
|
167 | 0 | return 0; |
168 | 0 | } |
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) */ |