I blindly copied this code from ptrace_resume() but it is wrong. task_is_stopped() can never be true, and we must not use ->sighand directly. Since the tracee should be TRACED or killed we do not check tracee->state at all.
Fixes a couple of tests... --- kernel/ptrace.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) --- PU/kernel/ptrace.c~29_WAKEUP_COMPAT_BUG 2009-09-12 00:13:34.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-12 00:59:10.000000000 +0200 @@ -320,12 +320,13 @@ static void ptrace_wake_up(struct utrace struct task_struct *tracee, enum utrace_resume_action action) { + unsigned long flags; + /* preserve the compatibility bug */ - if (task_is_stopped(tracee)) { - spin_lock_irq(&tracee->sighand->siglock); - tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; - spin_unlock_irq(&tracee->sighand->siglock); - } + if (!lock_task_sighand(tracee, &flags)) + return; + tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; + unlock_task_sighand(tracee, &flags); // XXX: FIXME!!! racy. tracee->exit_code = 0; @@ -1134,10 +1135,11 @@ static int ptrace_resume(struct task_str do_notify_parent_cldstop(child, CLD_TRAPPED); read_unlock(&tasklist_lock); } else { - if (task_is_stopped(child)) { - spin_lock_irq(&child->sighand->siglock); + unsigned long flags; + + if (lock_task_sighand(child, &flags)) { child->signal->flags &= ~SIGNAL_STOP_STOPPED; - spin_unlock_irq(&child->sighand->siglock); + unlock_task_sighand(child, &flags); } /*