All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stas Sergeev <stsp@aknet.ru>
To: linux-kernel@vger.kernel.org
Subject: [RFC][patch] PR_DETACH: detach from parent
Date: Fri, 24 Dec 2010 21:15:30 +0300	[thread overview]
Message-ID: <4D14E342.3010402@aknet.ru> (raw)

[-- Attachment #1: Type: text/plain, Size: 1693 bytes --]

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?

[-- Attachment #2: pr_detach.diff --]
[-- Type: text/plain, Size: 1587 bytes --]

diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index a3baeb2..fbd2451 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -102,4 +102,6 @@
 
 #define PR_MCE_KILL_GET 34
 
+#define PR_DETACH 35
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/kernel/signal.c b/kernel/signal.c
index 4e3cff1..2cd495a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -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;
diff --git a/kernel/sys.c b/kernel/sys.c
index 7f5a0cd..fa10732 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -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;

             reply	other threads:[~2011-01-22  8:34 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-24 18:15 Stas Sergeev [this message]
  -- strict thread matches above, loose matches on Subject: below --
2010-12-25 17:45 [RFC][patch] PR_DETACH: detach from parent Stas Sergeev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4D14E342.3010402@aknet.ru \
    --to=stsp@aknet.ru \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.