summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndorz Nilsson <andorz.nilsson@axis.com>2009-10-18 03:49:00 +0200
committerLennart Poettering <lennart@poettering.net>2009-10-18 03:49:00 +0200
commite81e87f8d408d965b3baab14910eb0b08c428600 (patch)
tree1c7482922ac2756ceeef590a3ea24637bc936855
parenta07c294e3d8242c98e6ada199268fde6bad1574b (diff)
dfork: clean up forking logic
Call setsid() once only to make sure we get a process that is not a session leader or process group leader, and hence cannot acquire a controlling terminal. It looks like setpgid() (or setpgrp()) is used only when setsid() is not available. It looks like the call to ioctl() is necessary only for 4.3BSD. (Patch modified by Lennart Poettering)
-rw-r--r--libdaemon/dfork.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/libdaemon/dfork.c b/libdaemon/dfork.c
index 2f57f1c..5fe8b7b 100644
--- a/libdaemon/dfork.c
+++ b/libdaemon/dfork.c
@@ -190,7 +190,10 @@ pid_t daemon_fork(void) {
} else if (pid == 0) {
pid_t dpid;
- /* First child */
+ /* First child. Now we are sure not to be a session leader or
+ * process group leader anymore, i.e. we know that setsid()
+ * will succeed. */
+
if (daemon_log_use & DAEMON_LOG_AUTO)
daemon_log_use = DAEMON_LOG_SYSLOG;
@@ -202,6 +205,7 @@ pid_t daemon_fork(void) {
/* Move file descriptors up*/
if (move_fd_up(&pipe_fds[1]) < 0)
goto fail;
+
if (_daemon_retval_pipe[0] >= 0 && move_fd_up(&_daemon_retval_pipe[0]) < 0)
goto fail;
if (_daemon_retval_pipe[1] >= 0 && move_fd_up(&_daemon_retval_pipe[1]) < 0)
@@ -222,9 +226,16 @@ pid_t daemon_fork(void) {
goto fail;
}
- setsid();
- setpgid(0, 0);
- umask(0777);
+ /* Create a new session. This will create a new session and a
+ * new process group for us and we will be the ledaer of
+ * both. This should always succeed because we cannot be the
+ * process group leader because we just forked. */
+ if (setsid() < 0) {
+ daemon_log(LOG_ERR, "setsid() failed: %s", strerror(errno));
+ goto fail;
+ }
+
+ umask(0077);
if (chdir("/") < 0) {
daemon_log(LOG_ERR, "chdir() failed: %s", strerror(errno));
@@ -236,10 +247,12 @@ pid_t daemon_fork(void) {
goto fail;
} else if (pid == 0) {
-#ifdef TIOCNOTTY
- int tty_fd;
-#endif
- /* Second child */
+ /* Second child. Our father will exit right-away. That way
+ * we can be sure that we are a child of init now, even if
+ * the process which spawned us stays around for a longer
+ * time. Also, since we are no session leader anymore we
+ * can be sure that we will never acquire a controlling
+ * TTY. */
if (sigaction(SIGCHLD, &sa_old, NULL) < 0) {
daemon_log(LOG_ERR, "close() failed: %s", strerror(errno));
@@ -266,15 +279,6 @@ pid_t daemon_fork(void) {
goto fail;
}
- setsid();
- setpgid(0, 0);
-
-#ifdef TIOCNOTTY
- if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
- ioctl(tty_fd, TIOCNOTTY, NULL);
- close(tty_fd);
- }
-#endif
dpid = getpid();
if (atomic_write(pipe_fds[1], &dpid, sizeof(dpid)) != sizeof(dpid)) {
daemon_log(LOG_ERR, "write() failed: %s", strerror(errno));