Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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/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(). */
36static int start_daemon_called = 0;
37/** True iff we've called finish_daemon(). */
38static int finish_daemon_called = 0;
39/** Socketpair used to communicate between parent and child process while
40 * daemonizing. */
41static int daemon_filedes[2];
42
43/**
44 * Return true iff we've called start_daemon() at least once.
45 */
46bool
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 */
58int
60{
61 pid_t pid;
62
64 return 0;
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 */
121int
122finish_daemon(const char *desired_cwd)
123{
124 int nullfd;
125 char c = '.';
127 return 0;
129 start_daemon();
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) */
171int
172start_daemon(void)
173{
174 return 0;
175}
176int
177finish_daemon(const char *cp)
178{
179 (void)cp;
180 return 0;
181}
182bool
184{
185 return false;
186}
187
188#endif /* !defined(_WIN32) */
void set_main_thread(void)
static int finish_daemon_called
Definition: daemon.c:38
bool start_daemon_has_been_called(void)
Definition: daemon.c:47
int start_daemon(void)
Definition: daemon.c:59
int finish_daemon(const char *desired_cwd)
Definition: daemon.c:122
static int daemon_filedes[2]
Definition: daemon.c:41
static int start_daemon_called
Definition: daemon.c:36
Header for daemon.c.
Header for fdio.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.