diff options
author | Nick Mathewson <nickm@torproject.org> | 2004-01-03 22:40:49 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2004-01-03 22:40:49 +0000 |
commit | cacacfe2b1f147c81cb05ddd5c6163cf482d5bed (patch) | |
tree | b13e7dcc9c250840b1c00e6e0a3d0e494f04e1b5 /src/common | |
parent | 7622a80904e4b06935d69c38d4a0e9cfc8c8b066 (diff) | |
download | tor-cacacfe2b1f147c81cb05ddd5c6163cf482d5bed.tar tor-cacacfe2b1f147c81cb05ddd5c6163cf482d5bed.tar.gz |
Integrate new daemon code, adapted from submission by christian grothoff
svn:r969
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/util.c | 104 | ||||
-rw-r--r-- | src/common/util.h | 14 |
2 files changed, 98 insertions, 20 deletions
diff --git a/src/common/util.c b/src/common/util.c index 4d9a44953..98b16a59b 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -696,31 +696,97 @@ get_uname(void) return uname_result; } -void daemonize(void) { -#ifdef HAVE_DAEMON - if (daemon(0 /* chdir to / */, - 0 /* Redirect std* to /dev/null */)) { - log_fn(LOG_ERR, "Daemon returned an error: %s", strerror(errno)); +#ifndef MS_WINDOWS +/* Based on code contributed by christian grothoff */ +static int start_daemon_called = 0; +static int finish_daemon_called = 0; +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); } -#elif ! defined(MS_WINDOWS) - /* Fork; parent exits. */ - if (fork()) - exit(0); - /* Create new session; make sure we never get a terminal */ - setsid(); - if (fork()) - exit(0); + pipe(daemon_filedes); + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + if (pid) { /* Parent */ + int ok; + char c; - chdir("/"); - umask(000); + close(daemon_filedes[1]); /* we only read */ + 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 */ + + pid = setsid(); /* Detach from controlling terminal */ + /* + * Fork one more time, so the parent (the session group leader) can exit. + * 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; + } +} - fclose(stdin); - fclose(stdout); - fclose(stderr); -#endif +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) { #ifndef MS_WINDOWS diff --git a/src/common/util.h b/src/common/util.h index acb8ab82a..fd300fa80 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -86,7 +86,19 @@ int tor_socketpair(int family, int type, int protocol, int fd[2]); 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); int switch_id(char *user, char *group); |