Tor 0.4.9.0-alpha-dev
daemon.c
Go to the documentation of this file.
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(). */
35static int start_daemon_called = 0;
36/** True iff we've called finish_daemon(). */
37static int finish_daemon_called = 0;
38/** Socketpair used to communicate between parent and child process while
39 * daemonizing. */
40static int daemon_filedes[2];
41
42/**
43 * Return true iff we've called start_daemon() at least once.
44 */
45bool
47{
48 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 */
57int
59{
60 pid_t pid;
61
63 return 0;
65
66 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 pid = fork();
73 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 if (pid) { /* Parent */
80 int ok;
81 char c;
82
83 close(daemon_filedes[1]); /* we only read */
84 ok = -1;
85 while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
86 if (c == '.')
87 ok = 1;
88 }
89 fflush(stdout);
90 if (ok == 1)
91 exit(0); // exit ok: during daemonize, daemonizing.
92 else
93 exit(1); /* child reported error. exit ok: daemonize failed. */
94 return 0; // LCOV_EXCL_LINE unreachable
95 } else { /* Child */
96 close(daemon_filedes[0]); /* we only write */
97
98 (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 if (fork() != 0) {
106 exit(0); // exit ok: during daemonize, fork failed (2)
107 }
108 set_main_thread(); /* We are now the main thread. */
109
110 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 */
120int
121finish_daemon(const char *desired_cwd)
122{
123 int nullfd;
124 char c = '.';
126 return 0;
128 start_daemon();
130
131 if (!desired_cwd)
132 desired_cwd = "/";
133 /* Don't hold the wrong FS mounted */
134 if (chdir(desired_cwd) < 0) {
135 log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd);
136 exit(1); // exit ok: during daemonize, chdir failed.
137 }
138
139 nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
140 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 if (dup2(nullfd,0) < 0 ||
151 dup2(nullfd,1) < 0 ||
152 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 if (nullfd > 2)
159 close(nullfd);
160 /* signal success */
161 if (write(daemon_filedes[1], &c, sizeof(char)) != sizeof(char)) {
162 log_err(LD_GENERAL,"write failed. Exiting.");
163 }
164 close(daemon_filedes[1]);
165
166 return 0;
167}
168#else /* defined(_WIN32) */
169/* defined(_WIN32) */
170int
171start_daemon(void)
172{
173 return 0;
174}
175int
176finish_daemon(const char *cp)
177{
178 (void)cp;
179 return 0;
180}
181bool
183{
184 return false;
185}
186
187#endif /* !defined(_WIN32) */
void set_main_thread(void)
static int finish_daemon_called
Definition: daemon.c:37
bool start_daemon_has_been_called(void)
Definition: daemon.c:46
int start_daemon(void)
Definition: daemon.c:58
int finish_daemon(const char *desired_cwd)
Definition: daemon.c:121
static int daemon_filedes[2]
Definition: daemon.c:40
static int start_daemon_called
Definition: daemon.c:35
Header for daemon.c.
Wrappers for reading and writing data to files on disk.
int tor_open_cloexec(const char *path, int flags, unsigned mode)
Definition: files.c:54
Headers for log.c.
#define LD_GENERAL
Definition: log.h:62
Header for threads.c.