Commit 4c2e8e62 authored by Roland McGrath's avatar Roland McGrath Committed by Linus Torvalds

[PATCH] let SIGKILL wake TASK_TRACED

Upon reevaluation we think it is indeed safe to permit the race between
a ptrace call and the traced thread waking up, as long as it will never
get back to user mode.  This patch makes SIGKILL wake up threads in
TASK_TRACED.  That alone resolves most of the deadlock issues that
became possible with the introduction of TASK_TRACED, getting us back to
the killing behavior of 2.6.8 and before. 

This patch also further cleans up ptrace detaching, so that threads are
left in TASK_STOPPED only if a job control stop is actually in effect,
and otherwise resume.  This removes the past nuisances requiring a
SIGCONT to resume a thread even when it had a pending SIGKILL. 
Signed-off-by: default avatarRoland McGrath <roland@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 09207038
...@@ -38,25 +38,22 @@ void __ptrace_link(task_t *child, task_t *new_parent) ...@@ -38,25 +38,22 @@ void __ptrace_link(task_t *child, task_t *new_parent)
SET_LINKS(child); SET_LINKS(child);
} }
static inline int pending_resume_signal(struct sigpending *pending)
{
#define M(sig) (1UL << ((sig)-1))
return sigtestsetmask(&pending->signal, M(SIGCONT) | M(SIGKILL));
}
/* /*
* Turn a tracing stop into a normal stop now, since with no tracer there * Turn a tracing stop into a normal stop now, since with no tracer there
* would be no way to wake it up with SIGCONT or SIGKILL. If there was a * would be no way to wake it up with SIGCONT or SIGKILL. If there was a
* signal sent that would resume the child, but didn't because it was in * signal sent that would resume the child, but didn't because it was in
* TASK_TRACED, resume it now. * TASK_TRACED, resume it now.
* Requires that irqs be disabled.
*/ */
void ptrace_untrace(task_t *child) void ptrace_untrace(task_t *child)
{ {
spin_lock(&child->sighand->siglock); spin_lock(&child->sighand->siglock);
child->state = TASK_STOPPED; if (child->state == TASK_TRACED) {
if (pending_resume_signal(&child->pending) || if (child->signal->flags & SIGNAL_STOP_STOPPED) {
pending_resume_signal(&child->signal->shared_pending)) { child->state = TASK_STOPPED;
signal_wake_up(child, 1); } else {
signal_wake_up(child, 1);
}
} }
spin_unlock(&child->sighand->siglock); spin_unlock(&child->sighand->siglock);
} }
......
...@@ -587,15 +587,15 @@ void signal_wake_up(struct task_struct *t, int resume) ...@@ -587,15 +587,15 @@ void signal_wake_up(struct task_struct *t, int resume)
set_tsk_thread_flag(t, TIF_SIGPENDING); set_tsk_thread_flag(t, TIF_SIGPENDING);
/* /*
* If resume is set, we want to wake it up in the TASK_STOPPED case. * For SIGKILL, we want to wake it up in the stopped/traced case.
* We don't check for TASK_STOPPED because there is a race with it * We don't check t->state here because there is a race with it
* executing another processor and just now entering stopped state. * executing another processor and just now entering stopped state.
* By calling wake_up_process any time resume is set, we ensure * By using wake_up_state, we ensure the process will wake up and
* the process will wake up and handle its stop or death signal. * handle its death signal.
*/ */
mask = TASK_INTERRUPTIBLE; mask = TASK_INTERRUPTIBLE;
if (resume) if (resume)
mask |= TASK_STOPPED; mask |= TASK_STOPPED | TASK_TRACED;
if (!wake_up_state(t, mask)) if (!wake_up_state(t, mask))
kick_process(t); kick_process(t);
} }
...@@ -935,11 +935,11 @@ __group_complete_signal(int sig, struct task_struct *p) ...@@ -935,11 +935,11 @@ __group_complete_signal(int sig, struct task_struct *p)
/* /*
* Don't bother traced and stopped tasks (but * Don't bother traced and stopped tasks (but
* SIGKILL will punch through stopped state) * SIGKILL will punch through that).
*/ */
mask = TASK_TRACED; mask = TASK_STOPPED | TASK_TRACED;
if (sig != SIGKILL) if (sig == SIGKILL)
mask |= TASK_STOPPED; mask = 0;
/* /*
* Now find a thread we can wake up to take the signal off the queue. * Now find a thread we can wake up to take the signal off the queue.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment