|
@@ -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);
|
|
|
|
|
|
- /*
|
|
|
|
- * 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)
|
|
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);
|
|
- /*
|
|
|
|
- * 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
|
|
/* 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->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))
|
|
&& !capable(CAP_KILL))
|
|
tsk->exit_signal = SIGCHLD;
|
|
tsk->exit_signal = SIGCHLD;
|
|
|
|
|