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>
This commit is contained in:
committed by
Linus Torvalds
parent
5ce2087ed0
commit
f49ee505b1
@@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
* 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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user