introduce kill_orphaned_pgrp() helper
authorOleg Nesterov <oleg@tv-sign.ru>
Sun, 2 Mar 2008 18:44:40 +0000 (21:44 +0300)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 3 Mar 2008 22:53:16 +0000 (14:53 -0800)
Factor out the common code in reparent_thread() and exit_notify().

No functional changes.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
kernel/exit.c

index 506a957b665a69bbf84794e233b8032f2d98b280..11fcce760151435cb0afcbc640231f52b0de471c 100644 (file)
@@ -255,6 +255,37 @@ static int has_stopped_jobs(struct pid *pgrp)
        return retval;
 }
 
+/*
+ * Check to see if any process groups have become orphaned as
+ * a result of our exiting, and if they have any stopped jobs,
+ * send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
+ */
+static void
+kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent)
+{
+       struct pid *pgrp = task_pgrp(tsk);
+       struct task_struct *ignored_task = tsk;
+
+       if (!parent)
+                /* exit: our father is in a different pgrp than
+                 * we are and we were the only connection outside.
+                 */
+               parent = tsk->real_parent;
+       else
+               /* reparent: our child is in a different pgrp than
+                * we are, and it was the only connection outside.
+                */
+               ignored_task = NULL;
+
+       if (task_pgrp(parent) != pgrp &&
+           task_session(parent) == task_session(tsk) &&
+           will_become_orphaned_pgrp(pgrp, ignored_task) &&
+           has_stopped_jobs(pgrp)) {
+               __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
+               __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
+       }
+}
+
 /**
  * reparent_to_kthreadd - Reparent the calling kernel thread to kthreadd
  *
@@ -635,22 +666,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
            p->exit_signal != -1 && thread_group_empty(p))
                do_notify_parent(p, p->exit_signal);
 
-       /*
-        * process group orphan check
-        * Case ii: Our child is in a different pgrp
-        * than we are, and it was the only connection
-        * outside, so the child pgrp is now orphaned.
-        */
-       if ((task_pgrp(p) != task_pgrp(father)) &&
-           (task_session(p) == task_session(father))) {
-               struct pid *pgrp = task_pgrp(p);
-
-               if (will_become_orphaned_pgrp(pgrp, NULL) &&
-                   has_stopped_jobs(pgrp)) {
-                       __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
-                       __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
-               }
-       }
+       kill_orphaned_pgrp(p, father);
 }
 
 /*
@@ -738,8 +754,6 @@ static void forget_original_parent(struct task_struct *father)
 static void exit_notify(struct task_struct *tsk)
 {
        int state;
-       struct task_struct *t;
-       struct pid *pgrp;
 
        /*
         * This does two things:
@@ -753,25 +767,7 @@ static void exit_notify(struct task_struct *tsk)
        exit_task_namespaces(tsk);
 
        write_lock_irq(&tasklist_lock);
-       /*
-        * Check to see if any process groups have become orphaned
-        * as a result of our exiting, and if they have any stopped
-        * jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
-        *
-        * Case i: Our father is in a different pgrp than we are
-        * and we were the only connection outside, so our pgrp
-        * is about to become orphaned.
-        */
-       t = tsk->real_parent;
-
-       pgrp = task_pgrp(tsk);
-       if ((task_pgrp(t) != pgrp) &&
-           (task_session(t) == task_session(tsk)) &&
-           will_become_orphaned_pgrp(pgrp, tsk) &&
-           has_stopped_jobs(pgrp)) {
-               __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
-               __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
-       }
+       kill_orphaned_pgrp(tsk, NULL);
 
        /* Let father know we died
         *
@@ -788,8 +784,8 @@ static void exit_notify(struct task_struct *tsk)
         * the same after a fork.
         */
        if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 &&
-           ( tsk->parent_exec_id != t->self_exec_id  ||
-             tsk->self_exec_id != tsk->parent_exec_id)
+           (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
+            tsk->self_exec_id != tsk->parent_exec_id)
            && !capable(CAP_KILL))
                tsk->exit_signal = SIGCHLD;