Commit f49ee505 authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds

introduce kill_orphaned_pgrp() helper

Factor out the common code in reparent_thread() and exit_notify().

No functional changes.
Signed-off-by: default avatarOleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5ce2087e
...@@ -255,6 +255,37 @@ static int has_stopped_jobs(struct pid *pgrp) ...@@ -255,6 +255,37 @@ static int has_stopped_jobs(struct pid *pgrp)
return retval; 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 * 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) ...@@ -635,22 +666,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
p->exit_signal != -1 && thread_group_empty(p)) p->exit_signal != -1 && thread_group_empty(p))
do_notify_parent(p, p->exit_signal); do_notify_parent(p, p->exit_signal);
/* kill_orphaned_pgrp(p, father);
* 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);
}
}
} }
/* /*
...@@ -738,8 +754,6 @@ static void forget_original_parent(struct task_struct *father) ...@@ -738,8 +754,6 @@ static void forget_original_parent(struct task_struct *father)
static void exit_notify(struct task_struct *tsk) static void exit_notify(struct task_struct *tsk)
{ {
int state; int state;
struct task_struct *t;
struct pid *pgrp;
/* /*
* This does two things: * This does two things:
...@@ -753,25 +767,7 @@ static void exit_notify(struct task_struct *tsk) ...@@ -753,25 +767,7 @@ static void exit_notify(struct task_struct *tsk)
exit_task_namespaces(tsk); exit_task_namespaces(tsk);
write_lock_irq(&tasklist_lock); write_lock_irq(&tasklist_lock);
/* kill_orphaned_pgrp(tsk, NULL);
* 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);
}
/* Let father know we died /* Let father know we died
* *
...@@ -788,8 +784,8 @@ static void exit_notify(struct task_struct *tsk) ...@@ -788,8 +784,8 @@ static void exit_notify(struct task_struct *tsk)
* the same after a fork. * the same after a fork.
*/ */
if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 && if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 &&
( tsk->parent_exec_id != t->self_exec_id || (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
tsk->self_exec_id != tsk->parent_exec_id) tsk->self_exec_id != tsk->parent_exec_id)
&& !capable(CAP_KILL)) && !capable(CAP_KILL))
tsk->exit_signal = SIGCHLD; tsk->exit_signal = SIGCHLD;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment