From: Paul E. McKenney Date: Sun, 8 Jan 2006 09:01:38 +0000 (-0800) Subject: [PATCH] Simpler signal-exit concurrency handling X-Git-Tag: v2.6.16-rc1~840 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d89c929078588aa9b9c674ef03ee9aa816b59b8;p=linux-2.6 [PATCH] Simpler signal-exit concurrency handling Some simplification in checking signal delivery against concurrent exit. Instead of using get_task_struct_rcu(), which increments the task_struct reference count, check the reference count after acquiring sighand lock. Signed-off-by: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/kernel/signal.c b/kernel/signal.c index 64737c72da..9b6fda5e87 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1102,18 +1102,19 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) retry: ret = check_kill_permission(sig, info, p); - if (!ret && sig && (sp = p->sighand)) { - if (!get_task_struct_rcu(p)) - return -ESRCH; + if (!ret && sig && (sp = rcu_dereference(p->sighand))) { spin_lock_irqsave(&sp->siglock, flags); if (p->sighand != sp) { spin_unlock_irqrestore(&sp->siglock, flags); - put_task_struct(p); goto retry; } + if ((atomic_read(&sp->count) == 0) || + (atomic_read(&p->usage) == 0)) { + spin_unlock_irqrestore(&sp->siglock, flags); + return -ESRCH; + } ret = __group_send_sig_info(sig, info, p); spin_unlock_irqrestore(&sp->siglock, flags); - put_task_struct(p); } return ret;