mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 15:43:32 +01:00
Integrate new daemon code, adapted from submission by christian grothoff
svn:r969
This commit is contained in:
parent
7622a80904
commit
cacacfe2b1
@ -696,32 +696,98 @@ get_uname(void)
|
|||||||
return uname_result;
|
return uname_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void daemonize(void) {
|
#ifndef MS_WINDOWS
|
||||||
#ifdef HAVE_DAEMON
|
/* Based on code contributed by christian grothoff */
|
||||||
if (daemon(0 /* chdir to / */,
|
static int start_daemon_called = 0;
|
||||||
0 /* Redirect std* to /dev/null */)) {
|
static int finish_daemon_called = 0;
|
||||||
log_fn(LOG_ERR, "Daemon returned an error: %s", strerror(errno));
|
static int daemon_filedes[2];
|
||||||
|
void start_daemon(void)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if (start_daemon_called)
|
||||||
|
return;
|
||||||
|
start_daemon_called = 1;
|
||||||
|
|
||||||
|
/* Don't hold the wrong FS mounted */
|
||||||
|
if (chdir("/") < 0) {
|
||||||
|
perror("chdir");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
#elif ! defined(MS_WINDOWS)
|
|
||||||
/* Fork; parent exits. */
|
|
||||||
if (fork())
|
|
||||||
exit(0);
|
|
||||||
|
|
||||||
/* Create new session; make sure we never get a terminal */
|
pipe(daemon_filedes);
|
||||||
setsid();
|
pid = fork();
|
||||||
if (fork())
|
if (pid < 0) {
|
||||||
exit(0);
|
perror("fork");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (pid) { /* Parent */
|
||||||
|
int ok;
|
||||||
|
char c;
|
||||||
|
|
||||||
chdir("/");
|
close(daemon_filedes[1]); /* we only read */
|
||||||
umask(000);
|
ok = -1;
|
||||||
|
while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
|
||||||
|
if (c == '.')
|
||||||
|
ok = 1;
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
if (ok == 1)
|
||||||
|
exit(0);
|
||||||
|
else
|
||||||
|
exit(1); /* child reported error */
|
||||||
|
} else { /* Child */
|
||||||
|
close(daemon_filedes[0]); /* we only write */
|
||||||
|
|
||||||
fclose(stdin);
|
pid = setsid(); /* Detach from controlling terminal */
|
||||||
fclose(stdout);
|
/*
|
||||||
fclose(stderr);
|
* Fork one more time, so the parent (the session group leader) can exit.
|
||||||
#endif
|
* This means that we, as a non-session group leader, can never regain a
|
||||||
|
* controlling terminal. This part is recommended by Stevens's
|
||||||
|
* _Advanced Programming in the Unix Environment_.
|
||||||
|
*/
|
||||||
|
if (fork() != 0) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void finish_daemon(void)
|
||||||
|
{
|
||||||
|
int nullfd;
|
||||||
|
char c = '.';
|
||||||
|
if (finish_daemon_called)
|
||||||
|
return;
|
||||||
|
if (!start_daemon_called)
|
||||||
|
start_daemon();
|
||||||
|
finish_daemon_called = 1;
|
||||||
|
|
||||||
|
nullfd = open("/dev/null",
|
||||||
|
O_CREAT | O_RDWR | O_APPEND);
|
||||||
|
if (nullfd < 0) {
|
||||||
|
perror("/dev/null");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* close fds linking to invoking terminal, but
|
||||||
|
* close usual incoming fds, but redirect them somewhere
|
||||||
|
* useful so the fds don't get reallocated elsewhere.
|
||||||
|
*/
|
||||||
|
if (dup2(nullfd,0) < 0 ||
|
||||||
|
dup2(nullfd,1) < 0 ||
|
||||||
|
dup2(nullfd,2) < 0) {
|
||||||
|
perror("dup2"); /* Should never happen... */
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
write(daemon_filedes[1], &c, sizeof(char)); /* signal success */
|
||||||
|
close(daemon_filedes[1]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* defined(MS_WINDOWS) */
|
||||||
|
void start_daemon(void) {}
|
||||||
|
void finish_daemon(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
void write_pidfile(char *filename) {
|
void write_pidfile(char *filename) {
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
FILE *pidfile;
|
FILE *pidfile;
|
||||||
|
@ -86,7 +86,19 @@ int tor_socketpair(int family, int type, int protocol, int fd[2]);
|
|||||||
|
|
||||||
const char *get_uname(void);
|
const char *get_uname(void);
|
||||||
|
|
||||||
void daemonize(void);
|
/* Start putting the process into daemon mode: fork and drop all resources
|
||||||
|
* except standard fds. The parent process never returns, but stays around
|
||||||
|
* until finish_daemon is called. (Note: it's safe to call this more
|
||||||
|
* than once: calls after the first are ignored.)
|
||||||
|
*/
|
||||||
|
void start_daemon(void);
|
||||||
|
/* Finish putting the process into daemon mode: drop standard fds, and tell
|
||||||
|
* the parent process to exit. (Note: it's safe to call this more than once:
|
||||||
|
* calls after the first are ignored. Calls start_daemon first if it hasn't
|
||||||
|
* been called already.)
|
||||||
|
*/
|
||||||
|
void finish_daemon(void);
|
||||||
|
|
||||||
void write_pidfile(char *filename);
|
void write_pidfile(char *filename);
|
||||||
int switch_id(char *user, char *group);
|
int switch_id(char *user, char *group);
|
||||||
|
|
||||||
|
@ -396,8 +396,6 @@ static int prepare_for_poll(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int init_from_config(int argc, char **argv) {
|
static int init_from_config(int argc, char **argv) {
|
||||||
static int have_daemonized=0;
|
|
||||||
|
|
||||||
if(getconfig(argc,argv,&options)) {
|
if(getconfig(argc,argv,&options)) {
|
||||||
log_fn(LOG_ERR,"Reading config failed. For usage, try -h.");
|
log_fn(LOG_ERR,"Reading config failed. For usage, try -h.");
|
||||||
return -1;
|
return -1;
|
||||||
@ -424,9 +422,9 @@ static int init_from_config(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(options.RunAsDaemon && !have_daemonized) {
|
if(options.RunAsDaemon) {
|
||||||
daemonize();
|
/* XXXX Can we delay this any more? */
|
||||||
have_daemonized = 1;
|
finish_daemon();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write our pid to the pid file, if we do not have write permissions we will log a warning */
|
/* write our pid to the pid file, if we do not have write permissions we will log a warning */
|
||||||
@ -633,6 +631,10 @@ int tor_main(int argc, char *argv[]) {
|
|||||||
if (init_from_config(argc,argv) < 0)
|
if (init_from_config(argc,argv) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (options.RunAsDaemon) {
|
||||||
|
start_daemon();
|
||||||
|
}
|
||||||
|
|
||||||
if(options.ORPort) { /* only spawn dns handlers if we're a router */
|
if(options.ORPort) { /* only spawn dns handlers if we're a router */
|
||||||
dns_init(); /* initialize the dns resolve tree, and spawn workers */
|
dns_init(); /* initialize the dns resolve tree, and spawn workers */
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user