The parting signal must not be visible to the next attacher. Compatibility!
Change ptrace_detach_task() to set context->resume = UTRACE_DETACH and do utrace_control(UTRACE_RESUME) in case the tracee should process the signal. If the tracee is killed we don't care what will happen. Otherwise it ptrace_report_signal(UTRACE_SIGNAL_REPORT) must be called, it will return UTRACE_DETACH and complete the detach. TODO: - re-check UTRACE_SIGNAL_HANDLER is not possible - info->si_pid will be wrong if sig != si_signo. how can we fix this? can't we ignore the problem? upstream is buggy too, I hope we can - the next attach is not possible until the tracee does ptrace_report_signal(). Fixed by the next patches. --- kernel/ptrace.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~75_DETACHED_ENGINE 2009-10-09 16:49:32.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-09 17:14:30.000000000 +0200 @@ -87,9 +87,12 @@ static struct utrace_engine *ptrace_look &ptrace_utrace_ops, NULL); } -static void detach_signal(struct task_struct *tracee, +static enum utrace_resume_action +detach_signal(struct task_struct *tracee, struct ptrace_context *context, int sig) { + enum utrace_resume_action action = UTRACE_DETACH; + switch (get_stop_event(context)) { case PTRACE_EVENT_SYSCALL_ENTRY: case PTRACE_EVENT_SYSCALL_EXIT: @@ -98,26 +101,30 @@ static void detach_signal(struct task_st break; case PTRACE_EVENT_SIGNAL: - if (!valid_signal(sig)) - sig = context->signr; - if (sig) - send_sig_info(sig, SEND_SIG_PRIV, tracee); + if (valid_signal(sig)) + context->signr = sig; + context->stop_code = 0; + context->resume = UTRACE_DETACH; + action = UTRACE_RESUME; break; } + + return action; } static void ptrace_detach_task(struct task_struct *child, int sig) { struct utrace_engine *engine = ptrace_lookup_engine(child); + enum utrace_resume_action action = UTRACE_DETACH; int ret; if (unlikely(IS_ERR(engine))) return; if (sig) - detach_signal(child, ptrace_context(engine), sig); + action = detach_signal(child, ptrace_context(engine), sig); - ret = utrace_control(child, engine, UTRACE_DETACH); + ret = utrace_control(child, engine, action); WARN_ON(ret && ret != -EINPROGRESS && ret != -ESRCH && ret != -EALREADY);