Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+35 −39
Original line number Diff line number Diff line
@@ -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,7 +784,7 @@ 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->parent_exec_id != tsk->real_parent->self_exec_id ||
	     tsk->self_exec_id != tsk->parent_exec_id)
	    && !capable(CAP_KILL))
		tsk->exit_signal = SIGCHLD;