aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@tv-sign.ru>2008-03-02 13:44:40 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-03-03 17:53:16 -0500
commitf49ee505b1ecb5960984880740f09aba87f870dc (patch)
tree2ff1289ecd2741d3f9d3a298662bc9b5a6266a3d /kernel/exit.c
parent5ce2087ed0eb424e0889bdc9102727f65d2ecdde (diff)
introduce kill_orphaned_pgrp() helper
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>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c74
1 files changed, 35 insertions, 39 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 506a957b665a..11fcce760151 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -255,6 +255,37 @@ static int has_stopped_jobs(struct pid *pgrp)
255 return retval; 255 return retval;
256} 256}
257 257
258/*
259 * Check to see if any process groups have become orphaned as
260 * a result of our exiting, and if they have any stopped jobs,
261 * send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
262 */
263static void
264kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent)
265{
266 struct pid *pgrp = task_pgrp(tsk);
267 struct task_struct *ignored_task = tsk;
268
269 if (!parent)
270 /* exit: our father is in a different pgrp than
271 * we are and we were the only connection outside.
272 */
273 parent = tsk->real_parent;
274 else
275 /* reparent: our child is in a different pgrp than
276 * we are, and it was the only connection outside.
277 */
278 ignored_task = NULL;
279
280 if (task_pgrp(parent) != pgrp &&
281 task_session(parent) == task_session(tsk) &&
282 will_become_orphaned_pgrp(pgrp, ignored_task) &&
283 has_stopped_jobs(pgrp)) {
284 __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
285 __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
286 }
287}
288
258/** 289/**
259 * reparent_to_kthreadd - Reparent the calling kernel thread to kthreadd 290 * reparent_to_kthreadd - Reparent the calling kernel thread to kthreadd
260 * 291 *
@@ -635,22 +666,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
635 p->exit_signal != -1 && thread_group_empty(p)) 666 p->exit_signal != -1 && thread_group_empty(p))
636 do_notify_parent(p, p->exit_signal); 667 do_notify_parent(p, p->exit_signal);
637 668
638 /* 669 kill_orphaned_pgrp(p, father);
639 * process group orphan check
640 * Case ii: Our child is in a different pgrp
641 * than we are, and it was the only connection
642 * outside, so the child pgrp is now orphaned.
643 */
644 if ((task_pgrp(p) != task_pgrp(father)) &&
645 (task_session(p) == task_session(father))) {
646 struct pid *pgrp = task_pgrp(p);
647
648 if (will_become_orphaned_pgrp(pgrp, NULL) &&
649 has_stopped_jobs(pgrp)) {
650 __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
651 __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
652 }
653 }
654} 670}
655 671
656/* 672/*
@@ -738,8 +754,6 @@ static void forget_original_parent(struct task_struct *father)
738static void exit_notify(struct task_struct *tsk) 754static void exit_notify(struct task_struct *tsk)
739{ 755{
740 int state; 756 int state;
741 struct task_struct *t;
742 struct pid *pgrp;
743 757
744 /* 758 /*
745 * This does two things: 759 * This does two things:
@@ -753,25 +767,7 @@ static void exit_notify(struct task_struct *tsk)
753 exit_task_namespaces(tsk); 767 exit_task_namespaces(tsk);
754 768
755 write_lock_irq(&tasklist_lock); 769 write_lock_irq(&tasklist_lock);
756 /* 770 kill_orphaned_pgrp(tsk, NULL);
757 * Check to see if any process groups have become orphaned
758 * as a result of our exiting, and if they have any stopped
759 * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
760 *
761 * Case i: Our father is in a different pgrp than we are
762 * and we were the only connection outside, so our pgrp
763 * is about to become orphaned.
764 */
765 t = tsk->real_parent;
766
767 pgrp = task_pgrp(tsk);
768 if ((task_pgrp(t) != pgrp) &&
769 (task_session(t) == task_session(tsk)) &&
770 will_become_orphaned_pgrp(pgrp, tsk) &&
771 has_stopped_jobs(pgrp)) {
772 __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
773 __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
774 }
775 771
776 /* Let father know we died 772 /* Let father know we died
777 * 773 *
@@ -788,8 +784,8 @@ static void exit_notify(struct task_struct *tsk)
788 * the same after a fork. 784 * the same after a fork.
789 */ 785 */
790 if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 && 786 if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 &&
791 ( tsk->parent_exec_id != t->self_exec_id || 787 (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
792 tsk->self_exec_id != tsk->parent_exec_id) 788 tsk->self_exec_id != tsk->parent_exec_id)
793 && !capable(CAP_KILL)) 789 && !capable(CAP_KILL))
794 tsk->exit_signal = SIGCHLD; 790 tsk->exit_signal = SIGCHLD;
795 791