PR_DETACH: detach from parent
RFC PATCH 1/1 PR_DETACH: detach from parent
Hi.
I was trying to use daemon() library call to daemonize the process, and found out that it is not suitable for the process that have threads: all the threads are simply being killed.
The reason is that the daemon() function does fork(), then exit() in parent and setsid() in child, which is a bit ugly, and doesn't work with threads (fork() doesn't fork threads).
I've found no solution to that, and just hacked up one instead.
The attached patch adds the PR_DETACH prctl command, which detaches the process from its parent. With that, the daemon() function can be implemented without the fork/exit/setsid hacks, and here is an example of it:
---
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/prctl.h>
#ifndef PR_DETACH
#define PR_DETACH 35
#endif
int daemon2(int nochdir, int noclose)
{
int err, fd;
err = prctl(PR_DETACH);
if (err == -1) {
if (errno == EINVAL)
errno = ENOTSUP;
return -1;
}
fd = open("/dev/tty", O_RDWR);
if (fd != -1) {
ioctl(fd, TIOCNOTTY, NULL);
close(fd);
}
if (!nochdir && chdir("/") == -1)
return -1;
if (!noclose) {
fd = open("/dev/null", O_RDWR, 0);
if (fd == -1)
return -1;
if (dup2(fd, STDIN_FILENO) == -1)
return -1;
if (dup2(fd, STDOUT_FILENO) == -1)
return -1;
if (dup2(fd, STDERR_FILENO) == -1)
return -1;
if (fd > 2)
close(fd);
}
return 0;
}---
With this implementation, all threads survive the daemonization. Thoughts?
include/linux/prctl.h +2 -0
@@ -102,4 +102,6 @@#define PR_MCE_KILL_GET 34 +#define PR_DETACH 35 +#endif /* _LINUX_PRCTL_H */
kernel/signal.c +3 -3
@@ -1450,10 +1450,10 @@ int do_notify_parent(struct task_struct *tsk, int sig)BUG_ON (sig ==-1 ); -/* do_notify_parent_cldstop should have been called instead. */ -BUG_ON (task_is_stopped_or_traced (tsk)); +/* do_notify_parent_cldstop should have been called instead. */ +BUG_ON (task_is_stopped_or_traced (tsk)); -BUG_ON (!task_ptrace (tsk) && +BUG_ON (!task_ptrace (tsk) && (tsk->flags &PF_EXITING ) && (tsk->group_leader != tsk || !thread_group_empty (tsk))); info.si_signo = sig;
kernel/sys.c +15 -0
@@ -1727,6 +1727,21 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,else error =PR_MCE_KILL_DEFAULT ;break ; +case PR_DETACH : + error = -EPERM ; +if (me->real_parent == init_pid_ns.child_reaper) +break ; +if (me->group_leader != me) +break ; +exit_ptrace (me); +do_notify_parent (me, me->exit_signal); + me->exit_signal =SIGCHLD ; + me->parent = me->real_parent = + init_pid_ns.child_reaper; +list_move_tail (&me->sibling, + &me->real_parent->children); + error =0 ; +break ;default : error = -EINVAL ;break ;