linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] move the related code from exit_notify() to exit_signals()
@ 2007-12-06 16:22 Oleg Nesterov
  2007-12-07  0:56 ` Davide Libenzi
  0 siblings, 1 reply; 2+ messages in thread
From: Oleg Nesterov @ 2007-12-06 16:22 UTC (permalink / raw)
  To: Andrew Morton, Davide Libenzi, Ingo Molnar, Linus Torvalds,
	Roland McGrath
  Cc: linux-kernel

The previous bugfix was not optimal, we shouldn't care about group stop when
we are the only thread or the group stop is in progress. In that case nothing
special is needed, just set PF_EXITING and return.

Also, take the related "TIF_SIGPENDING re-targeting" code from exit_notify().

So, from the performance POV the only difference is that we don't trust
!signal_pending() until we take ->siglock. But this in fact fixes another
___pure___ theoretical minor race. __group_complete_signal() finds the task
without PF_EXITING and chooses it as the target for signal_wake_up(). But
nothing prevents this task from exiting in between without noticing the
pending signal and thus unpredictably delaying the actual delivery.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>

--- PT/kernel/exit.c~2_unify_signal_exit	2007-12-05 19:50:26.000000000 +0300
+++ PT/kernel/exit.c	2007-12-06 18:06:09.000000000 +0300
@@ -743,24 +743,6 @@ static void exit_notify(struct task_stru
 	struct task_struct *t;
 	struct pid *pgrp;
 
-	if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
-	    && !thread_group_empty(tsk)) {
-		/*
-		 * This occurs when there was a race between our exit
-		 * syscall and a group signal choosing us as the one to
-		 * wake up.  It could be that we are the only thread
-		 * alerted to check for pending signals, but another thread
-		 * should be woken now to take the signal since we will not.
-		 * Now we'll wake all the threads in the group just to make
-		 * sure someone gets all the pending signals.
-		 */
-		spin_lock_irq(&tsk->sighand->siglock);
-		for (t = next_thread(tsk); t != tsk; t = next_thread(t))
-			if (!signal_pending(t) && !(t->flags & PF_EXITING))
-				recalc_sigpending_and_wake(t);
-		spin_unlock_irq(&tsk->sighand->siglock);
-	}
-
 	/*
 	 * This does two things:
 	 *
--- PT/kernel/signal.c~2_unify_signal_exit	2007-12-05 20:17:20.000000000 +0300
+++ PT/kernel/signal.c	2007-12-06 18:13:31.000000000 +0300
@@ -1871,19 +1871,36 @@ relock:
 void exit_signals(struct task_struct *tsk)
 {
 	int group_stop = 0;
+	struct task_struct *t;
 
-	spin_lock_irq(&tsk->sighand->siglock);
-	if (unlikely(tsk->signal->group_stop_count) &&
-			!--tsk->signal->group_stop_count) {
-		tsk->signal->flags = SIGNAL_STOP_STOPPED;
-		group_stop = 1;
+	if (thread_group_empty(tsk) || signal_group_exit(tsk->signal)) {
+		tsk->flags |= PF_EXITING;
+		return;
 	}
 
+	spin_lock_irq(&tsk->sighand->siglock);
 	/*
 	 * From now this task is not visible for group-wide signals,
 	 * see wants_signal(), do_signal_stop().
 	 */
 	tsk->flags |= PF_EXITING;
+	if (!signal_pending(tsk))
+		goto out;
+
+	/* It could be that __group_complete_signal() choose us to
+	 * notify about group-wide signal. Another thread should be
+	 * woken now to take the signal since we will not.
+	 */
+	for (t = tsk; (t = next_thread(t)) != tsk; )
+		if (!signal_pending(t) && !(t->flags & PF_EXITING))
+			recalc_sigpending_and_wake(t);
+
+	if (unlikely(tsk->signal->group_stop_count) &&
+			!--tsk->signal->group_stop_count) {
+		tsk->signal->flags = SIGNAL_STOP_STOPPED;
+		group_stop = 1;
+	}
+out:
 	spin_unlock_irq(&tsk->sighand->siglock);
 
 	if (unlikely(group_stop)) {


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] move the related code from exit_notify() to exit_signals()
  2007-12-06 16:22 [PATCH] move the related code from exit_notify() to exit_signals() Oleg Nesterov
@ 2007-12-07  0:56 ` Davide Libenzi
  0 siblings, 0 replies; 2+ messages in thread
From: Davide Libenzi @ 2007-12-07  0:56 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Andrew Morton, Ingo Molnar, Linus Torvalds, Roland McGrath,
	Linux Kernel Mailing List

On Thu, 6 Dec 2007, Oleg Nesterov wrote:

> The previous bugfix was not optimal, we shouldn't care about group stop when
> we are the only thread or the group stop is in progress. In that case nothing
> special is needed, just set PF_EXITING and return.
> 
> Also, take the related "TIF_SIGPENDING re-targeting" code from exit_notify().
> 
> So, from the performance POV the only difference is that we don't trust
> !signal_pending() until we take ->siglock. But this in fact fixes another
> ___pure___ theoretical minor race. __group_complete_signal() finds the task
> without PF_EXITING and chooses it as the target for signal_wake_up(). But
> nothing prevents this task from exiting in between without noticing the
> pending signal and thus unpredictably delaying the actual delivery.

For a second there, you got me confused, since it wasn't clear to me this 
patch was going over the previous one. When posting patches that are not 
in any tree, it may be wise to include the set they nest onto ;)


> +	if (!signal_pending(tsk))
> +		goto out;
> +
> +	/* It could be that __group_complete_signal() choose us to
> +	 * notify about group-wide signal. Another thread should be
> +	 * woken now to take the signal since we will not.
> +	 */
> +	for (t = tsk; (t = next_thread(t)) != tsk; )
> +		if (!signal_pending(t) && !(t->flags & PF_EXITING))
> +			recalc_sigpending_and_wake(t);
> +
> +	if (unlikely(tsk->signal->group_stop_count) &&
> +			!--tsk->signal->group_stop_count) {
> +		tsk->signal->flags = SIGNAL_STOP_STOPPED;
> +		group_stop = 1;
> +	}
> +out:

Looks fine to me, even though the one above could simply be an:

if (signal_pending(tsk)) {
	...
}

(since the "out" label is used by that "if" only).



- Davide



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-12-07  0:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-12-06 16:22 [PATCH] move the related code from exit_notify() to exit_signals() Oleg Nesterov
2007-12-07  0:56 ` Davide Libenzi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).