From cfdc29de6c7ab89a793d2c91d4fc9248a8cab95a Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Wed, 30 Apr 2008 00:52:51 -0700 Subject: [PATCH] --- yaml --- r: 95124 b: refs/heads/master c: 3547ff3aefbe092ca35506c60c02e2d17a4f2199 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/kernel/signal.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index 35de8fa7d741..2d8dbc900d14 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6e65acba7ca8169e38ab55d62d52f29a75fb141f +refs/heads/master: 3547ff3aefbe092ca35506c60c02e2d17a4f2199 diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index b3dedf1f9323..13371d17358d 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -2219,6 +2219,7 @@ static int do_tkill(int tgid, int pid, int sig) int error; struct siginfo info; struct task_struct *p; + unsigned long flags; error = -ESRCH; info.si_signo = sig; @@ -2227,21 +2228,24 @@ static int do_tkill(int tgid, int pid, int sig) info.si_pid = task_tgid_vnr(current); info.si_uid = current->uid; - read_lock(&tasklist_lock); + rcu_read_lock(); p = find_task_by_vpid(pid); if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) { error = check_kill_permission(sig, &info, p); /* * The null signal is a permissions and process existence * probe. No signal is actually delivered. + * + * If lock_task_sighand() fails we pretend the task dies + * after receiving the signal. The window is tiny, and the + * signal is private anyway. */ - if (!error && sig && p->sighand) { - spin_lock_irq(&p->sighand->siglock); + if (!error && sig && lock_task_sighand(p, &flags)) { error = specific_send_sig_info(sig, &info, p); - spin_unlock_irq(&p->sighand->siglock); + unlock_task_sighand(p, &flags); } } - read_unlock(&tasklist_lock); + rcu_read_unlock(); return error; }