Re: ptrace && task->exit_code

Roland McGrath
2009-06-01T02:17:17Z

> If we attach, and the task is already stopped, this really means
> it was traced and untraced. We can set ->exit_code = SIGSTOP to
> ensure do_wait() will succeed.

If you go that route you really need a do_notify_parent_cldstop() call too.
Obviously the tracer itself won't be blocked in wait while it's in the
middle of this ptrace call. But it might be relying on a designated thread
calling wait, or it might call wait only when provoked by SIGCHLD, etc.

If you do that, you might as well just do:

spin_lock(task->signal->siglock);
specific_send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
signal_wake_up(task, 1);
spin_unlock(task->signal->siglock);

That way PTRACE_ATTACH would have a uniform effect on task whether it
was stopped or not. It always gives the tracer a fresh stop, never
leaves another SIGSTOP queued afterwards, and it's always a proper
ptrace stop where the debugger gets the full range of options like
injecting a new signal and using PTRACE_SETSIGINFO. (OTOH, then the
debugger can't necessarily tell if the task had been stopped or not
before the attach.)

Jan will probably affirm that userland debuggers wish it had always been
this way. But real userland debuggers already cope with existing
kernels and will have to continue to cope with old kernels for a long
time to come. So I don't see that it buys anything to change it now.

> This also relates to attach-wait-on-stopped test-case, I cc'ed
> Jan and Denys.
>
> Note also that after
>
> do_wait: fix waiting for the group stop with the dead leader
> commit: 90bc8d8b1a38f1ab131a2399a202e1889db95de8
>
> we can't confuse task->real_parent waiting for jctl stop.

Hmm. I had not thought about how the 90bc8d8 change to touch
group_exit_code instead for real parents affected this ptrace area.

That means that PTRACE_ATTACH while already stopped but not waited-for
no longer "steals" the real parent's tracking of the child's stoppedness
when it had not yet done a wait after its SIGCHLD/wakeup. After detach,
that wait could happen just like it would have before the debugger came
along. However, nothing will wake up the parent's wait if it's already
blocked in one at detach time.

Thanks,
Roland