Re: utrace-ptrace detach with signal semantics
I'm replying out of order. So I'm sorry I started rehashing some of this same stuff in the other thread before reading where you'd already referred to it. What if the tracee reports a signal and stops, the tracer detaches but does not wake it up because of SIGNAL_STOP_STOPPED ? In this case this signal will be visible after the next attach. OK, currently ptrace_detach() unconditionally wakes up the tracee. But we seem to agree this wakeup should be killed, it completely breaks the group-stop logic and it has other problems. So today the manifest semantics in userland is that PTRACE_DETACH from a signal stop causes immediate delivery of the signal in that thread regardless of the group stoppedness. In a (converted) job stop or non-signal, non-syscall ptrace stop the tracee resumes and drops the passed signr on the floor. Those semantics are very clear for the single-threaded case at least, so we can just be compatible. In MT cases where the result is a group-exit, that is pretty consistent and reliable today, so we probably need to be compatible there too. In MT cases where the result is to flutter back into job stop (SIGSTOP et al), then there too it is reliable today that you'll get another SIGCHLD and wait wakeup to go with that freshly stopped again. In MT cases where the result is to confuse the group-stop state, i.e. tracee runs (signal handler or ignored signal) while group is supposedly stopped, we probably don't break anything not already broken by cleaning it up somehow. But if the tracer does a loop of PTRACE_DETACH on each tracee thread, then the result today is probably pretty consistent in manifest behavior today: they all get back to running, even if the SIGNAL_STOP_STOPPED flag is still set. But I'm not at all sure anything could discern from userland that SIGNAL_STOP_STOPPED is still set. It will be set anew or cleared by the time it actually matters. So maybe it really is consistent enough with today's observable behavior just to have PTRACE_DETACH clear SIGNAL_STOP_STOPPED. I'm guessing that will be pretty well consistent in the loop-of-detach case (by the end of it). I'm not really sure what would go different in an oddball case where you PTRACE_DETACH'd one thread but the others were actually left stopped (e.g. in true job stop and you only ever attached the one thread). But it probably doesn't much matter, that usage mode must already be pretty broken I would think. If monitor really wants to kill the tracee it should use SIGKILL ;) Say it wants a core dump. Any other fatal signal can be ignored by the tracee's sub-thread after detach but before the tracee returns from ptrace_signal(). Say they never tested the MT case before and haven't started caring about it now. They just want what they have observed before to stay the same as they saw with the old kernel. Since detach_signal() actually sends the signal, ptrace(DETACH, SIGKILL) really works: it wakes up SIGNAL_STOP_STOPPED tracee. Today's manifest behavior (via the bogus wake_up_process) is that this SIGKILL will get through and take effect (in signal stops, as above). So that should stay. As to the theory of things, this is the flip side of the whole SIGNAL_STOP_DEQUEUED issue I just posted about earlier. Whereas only an earlier SIGCONT/SIGKILL would have cleared stop signals and thus should clear any pending-equivalent half-delivered stop signals, earlier stop signals would have cleared a pending SIGCONT. I'm not entirely sure what should happen in all the SIGCONT cases, but we can probably enumerate them and hash those out. I doubt anybody is depending much on the corners of that. For the SIGKILL cases, it's more clear. No matter what, if a SIGKILL doesn't just get dropped on the floor (non-signal stop cases), then it's going to override everything else and soon. Lets discuss how we can implement detach to be compatible... We already discussed detached_ops. So, we either change engine-ops (my choice) or add the new engine with -ops = detached_ops and detach the ptrace engine. I don't recall all of the earlier discussion about this in detail. But yes, they are equivalent and I think a fresh engine is cleaner. We need detached_report_signal() callback which fixups siginfo if signr != info-si_signo and returns UTRACE_DETACH | UTRACE_SIGNAL_DELIVER. Right, ptrace_report_signal does that now with -resume = UTRACE_DETACH. How can detached_report_signal() set info-si_pid correctly? the tracer has gone away. This probably means this info should be prepared during detach, the tracer should fill context-siginfo. It means that if the tracer cared at all, he did PTRACE_SETSIGINFO so this would be moot. The vanilla kernel today uses si_pid and si_uid values of what's either the new tracer (with racing PTRACE_ATTACH) or the real parent at the time of actual resumption. It can be any of those values or 0 and I think it's fine. But the real problem, I can't see how can we teach
Re: utrace-ptrace detach with signal semantics
I think always-reply-to-all is the best policy ;) For some people's mail-handling habits it makes a difference, so it is always safest not to trim individuals. For me personally, I always see the list copies just the same as the ones CC'd to me personally, so I don't care to be in the CC list as long as the mailing list is CC'd (and I prefer shorter CC lists for no special reason). Thanks, Roland
Re: utrace-ptrace detach with signal semantics
On Sat, 10 Oct 2009 18:24:21 +0200, Oleg Nesterov wrote: On 10/06, Jan Kratochvil wrote: Yes, I agree with the current general behavior of ptrace there is missing: if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) [...snip...] --- attach-into-signal.c31 Jan 2009 21:11:40 - 1.5 +++ attach-into-signal.c6 Oct 2009 14:27:08 - @@ -224,6 +224,18 @@ static void reproduce (void) child = 0; return; } + /* SIGPIPE was still pending and it has not been yet delivered. */ + if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) +{ + /* Deliver it and get the queued SIGSTOP. */ + errno = 0; + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); + assert_perror (errno); + + errno = 0; + pid = waitpid (child, status, 0); + assert (pid == child); +} assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGSTOP); /* let tracee run. it must be killed very soon by SIGPIPE */ Jan, please revert this change. Reverted (VERBOSE-caught with FAIL now). Jan
Re: utrace-ptrace detach with signal semantics
On 10/10, Jan Kratochvil wrote: On Sat, 10 Oct 2009 18:24:21 +0200, Oleg Nesterov wrote: On 10/06, Jan Kratochvil wrote: Yes, I agree with the current general behavior of ptrace there is missing: if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) [...snip...] --- attach-into-signal.c 31 Jan 2009 21:11:40 - 1.5 +++ attach-into-signal.c 6 Oct 2009 14:27:08 - @@ -224,6 +224,18 @@ static void reproduce (void) child = 0; return; } + /* SIGPIPE was still pending and it has not been yet delivered. */ + if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) +{ + /* Deliver it and get the queued SIGSTOP. */ + errno = 0; + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); + assert_perror (errno); + + errno = 0; + pid = waitpid (child, status, 0); + assert (pid == child); +} assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGSTOP); /* let tracee run. it must be killed very soon by SIGPIPE */ Jan, please revert this change. Reverted Thanks! (VERBOSE-caught with FAIL now). Cough. please translate this to me ;) Oleg.
Re: utrace-ptrace detach with signal semantics
On Sat, 10 Oct 2009 18:48:29 +0200, Oleg Nesterov wrote: On 10/10, Jan Kratochvil wrote: (VERBOSE-caught with FAIL now). Cough. please translate this to me ;) (Cc of each such mail to Roland does not look OK to me but removing Ccs is also not OK) --- tests/attach-into-signal.c 6 Oct 2009 19:21:35 - 1.6 +++ tests/attach-into-signal.c 10 Oct 2009 16:47:46 - 1.7 @@ -227,14 +227,8 @@ static void reproduce (void) /* SIGPIPE was still pending and it has not been yet delivered. */ if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) { - /* Deliver it and get the queued SIGSTOP. */ - errno = 0; - ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); - assert_perror (errno); - - errno = 0; - pid = waitpid (child, status, 0); - assert (pid == child); + VERBOSE (Forbidden to catch pending signal from PTRACE_DETACH); + exit (1); } assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGSTOP);
Re: utrace-ptrace detach with signal semantics
On Wed, 07 Oct 2009 15:33:49 +0200, Oleg Nesterov wrote: On 10/06, Jan Kratochvil wrote: It should work also for PTRACE_SINGLESTEP. Heh. Yes, but with one exception. - the tracee has a hanlder for, say, SIGHUP - the tracee deques SIGHUP, reports to the tracer, and stops. - the tracer does ptrace(SINGLESTEP, SIGHUP) // it could use another signr, this works. // but the tracer must have a handler or // everething is OK. - the tracee delivers SIGHUP to itself, handle_signal() notices TIF_SINGLESTEP and calls ptrace_notify(). Now, the tracee reports SIGTRAP, but the next time the tracer does ptrace(WHATEVER, SIGNR) SIGNR will be ignored. OK, this is really a border case I did not mean. In such case the SIGHUP handler still is not fully execting and as the non-realtime signals do not nest (count) it is OK it gets activated only once. I did mean some more normal case of: ptrace (PTRACE_SIGNALSTEP, 0) = 0 waitpid() = SIGTRAP ptrace (PTRACE_SIGNALSTEP, 0) = 0 waitpid() = SIGTRAP PTRACE (PTRACE_DETACH, SIGSTOP) = 0 which I assume it will work. Thanks, Jan
Re: utrace-ptrace detach with signal semantics
On 10/07, Jan Kratochvil wrote: OK, this is really a border case I did not mean. In such case the SIGHUP handler still is not fully execting and as the non-realtime signals do not nest (count) it is OK it gets activated only once. I did mean some more normal case of: ptrace (PTRACE_SIGNALSTEP, 0) = 0 waitpid() = SIGTRAP ptrace (PTRACE_SIGNALSTEP, 0) = 0 waitpid() = SIGTRAP PTRACE (PTRACE_DETACH, SIGSTOP) = 0 which I assume it will work. Yes, this should work. In this case the tracee really has the pending SIGTRAP which will be dequeued and reported. ptrace(WHATEVER, SIGNR) will change si_signo (or cancel the signal if SIGNR = 0), PTRACE_SETSIGINFO works too. Oleg.
Re: utrace-ptrace detach with signal semantics
Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) and then another/same tracer does ptrace(ATTACH, tracee) then SIGXXX will not be reported to the new tracer. Correct. Why? Should utrace-ptrace be 100% compatible here? I think it should, yes. There is a rationale for it that makes sense to me, and it is most certainly consistent, observable behavior on which existing applications could very well depend subtly, so regardless of right I think this one is well within 100% bug-compatibility territory. The rationale I see is that the debugger observed the signal, decided it wanted the tracee to experience the normal effects of the signal and be done with it after that. If it's a termination signal, the debugger really expects that the tracee can do nothing but die. (Given the tortured historic logic of the ptrace code paths, this applies only to signal stops and only when it either passes back the same signal number or at least another one that is not blocked.) Now replace debugger with monitor or (dismal) security-checking syscall tracing product, or just shudder while trying not to imagine what all inane things ptrace might already be in use for. It could be important to someone out there e.g. that some other process of the tracee's UID cannot race in there and rescue it from dying. I do not think there is a real life application that does ATTACH + DETACH and relies on fact it must not see this sig. We can hope, but we cannot assume. There are always better ways to achieve the same true ends than the corner case examples like the one I gave, but that doesn't mean people haven't written the stupid ones in applications already shipped long ago and never to be rethought again (until we get the blame for breaking them in the new kernel). Thanks, Roland
Re: utrace-ptrace detach with signal semantics
Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. They should not, this is just wrong. And I think the proposed change doesn't change the behaviour in this sense. It does not in the general sense. But it does change the behavior of certain 100% predictable patterns that could have been used before. Thanks, Roland
Re: utrace-ptrace detach with signal semantics
OK. Let's see what Roland thinks. I think the whole stoppedness vs detach et al discussion is a separate issue from the basic PTRACE_DETACH,signr behavior, and I think I want to discuss that in the other thread we have whose subject says it's about that. I think I've covered the (separate) basic parting-signal issue now. Hmm. I guess with utrace it will be simple to do this change... You're supposed to say that before every patch! Didn't you get the memo? ;-) Thanks, Roland
Re: utrace-ptrace detach with signal semantics
In which specific cases SIGNR can get ignored? There are two fundamental kinds of ptrace stops: real signal stops, and fake (or ptrace_notify()) stops. In the latter, you are not in the right place in the kernel for direct signal delivery, so it never works fully normally. All the optional event stops are in this latter category, i.e. everything not for a signal. The syscall entry and exit stops have an explicit queuing behavior (i.e. it's about the same as if you'd just called tgkill before PTRACE_CONT--any PTRACE_SETSIGINFO you've done has no effect on this new signal, but you will see it in a real signal stop soon when it's dequeued). The others do not have any such kludge, so they just drop the signr argument on the floor. Note that the default exec stop really is a signal (a plain SIGTRAP sent as if by raise(SIGTRAP); right after exec), but PTRACE_EVENT_EXEC is not. Some of the PTRACE_SINGLESTEP cases on some architectures use fake stops. When stepping over an average user instruction, it's always a real SIGTRAP. But e.g., stepping the syscall insn on powerpc and some others (perhaps all but x86) is not. As Oleg mentioned, when PTRACE_SINGLESTEP,signr stops immediately after handler setup, that is also a fake stop. These cases are something that we probably can and should fix and arch-harmonize upstream so that PTRACE_SINGLESTEP consistently produces a real SIGTRAP signal stop after which the full range of I don't think the behavior for the special event stops will change. Thanks, Roland
Re: utrace-ptrace detach with signal semantics
after which the full range of [oops, left that thought unfinished!] ... signal control options works (immediate delivery, SETSIGIFNO obeyed)
Re: utrace-ptrace detach with signal semantics
On 10/06, Jan Kratochvil wrote: On Mon, 05 Oct 2009 21:00:37 +0200, Oleg Nesterov wrote: On 10/05, Jan Kratochvil wrote: On Mon, 05 Oct 2009 04:51:32 +0200, Oleg Nesterov wrote: Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) and then another/same tracer does ptrace(ATTACH, tracee) then SIGXXX will not be reported to the new tracer. Why? Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. They should not, this is just wrong. That may be a right point but such programs are in use out there. Sure if it would be a real difficulty one can keep it as-is as GDB-7.0 soon to be released has it already fixed, strace works with it. Still ltrace crashes the inferior in such case. Confused. Do you mean we should fix the kernel to match this expectation? This was never true. PTRACE_ATTACH sends SIGSTOP to the tracee, but this SIGSTOP is not magical, there is no any guarantee it will be dequeued before other pending signals. You attached the test-case which sends SIGALRM to itself in a loop. If the tracer attaches to this program, it is very possible that SIGALRM will be reported, not SIGSTOP. But! this has nothing to do with the question I asked ;) see below. And I think the proposed change doesn't change the behaviour in this sense. We started to discuss two different changes: We started to discuss 3 different things, not 2. Please see below, my question was quite different. my asked for one: ptrace(DETACH, SIGSTOP) should leave the tracee stopped. Yes, a new one: First signal after PTRACE_ATTACH should be SIGSTOP. This was never true, afaics. Of course, if nobody sends other signals to the tracee then SIGSTOP will be the first signal, but only because there are no other signals which could be dequeued/reported. It is not trivial to implement, and I don't understand why it is important to keep this behaviour. But we have the test case which checks this: attach-into-signal. This testcase is in fact PASSing even when non-SIGSTOP signal is sent as the first one after PTRACE_ATTACH. It has specific handling of such cases. This test-case also does: /* detach with SIGPIPE/attach. This should kill tracee */ ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); waitpid (child, status, 0); assert (WIFSIGNALED (status) WTERMSIG (status) == SIGPIPE); It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what I can't understand. attach-info-signal from the ptrace-testsuite does not FAIL for me. Which kernel version does it FAIL on for you? It fails on ptrace-over-utrace. And I can't understand why this behaviour is important. I hope it is not. Once again. Suppose that the tracer does ptrace(PTRACE_DETACH, SIGXXX). Currently, if the next thacer attaches right after this detach it has no way to intercept SIGXXX, it will be never reported via ptrace_signal(). Is this really important? Do you know any application which can be broken if we change this behaviour? With the current utrace-ptrace implementation SIGXXX can be reported to the new tracer. OK, this relates to the first signal should be SIGSTOP but this is wrong anyway, and the case above is very unlikely. Oleg.
Re: utrace-ptrace detach with signal semantics
On Tue, 06 Oct 2009 15:10:10 +0200, Oleg Nesterov wrote: On 10/06, Jan Kratochvil wrote: On Mon, 05 Oct 2009 21:00:37 +0200, Oleg Nesterov wrote: On 10/05, Jan Kratochvil wrote: Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. They should not, this is just wrong. That may be a right point but such programs are in use out there. Sure if it would be a real difficulty one can keep it as-is as GDB-7.0 soon to be released has it already fixed, strace works with it. Still ltrace crashes the inferior in such case. Confused. Do you mean we should fix the kernel to match this expectation? Yes, I was thinking it would be a good idea. This was never true. I agree. You attached the test-case which sends SIGALRM to itself in a loop. If the tracer attaches to this program, it is very possible that SIGALRM will be reported, not SIGSTOP. Yes. And the real world tracers do not expect so. This test-case also does: /* detach with SIGPIPE/attach. This should kill tracee */ ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); waitpid (child, status, 0); assert (WIFSIGNALED (status) WTERMSIG (status) == SIGPIPE); It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what I can't understand. Second keyword PTRACE_ATTACH is on line 167. First keyword SIGPIPE is on line 199. Line 167 cannot see anything from line 199. Assuming you did mean third PTRACE_ATTACH. Line 222: if (WIFSIGNALED (status) WTERMSIG (status) == SIGPIPE) Line 227: assert (WIFSTOPPED (status)); Line 228: assert (WSTOPSIG (status) == SIGSTOP); Yes, I agree with the current general behavior of ptrace there is missing: if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) It fails on ptrace-over-utrace. Attached, I do not have kernel.rpm with ptrace-over-utrace ready, please verify it and check it in (or ping me or so). Once again. Suppose that the tracer does ptrace(PTRACE_DETACH, SIGXXX). Currently, if the next thacer attaches right after this detach it has no way to intercept SIGXXX, it will be never reported via ptrace_signal(). No matter if it gets reported to the new tracer still SIGXXX should never get lost. If it is not reported to the new tracer then it will be always processed by the tracee, is it right? Is this really important? Do you know any application which can be broken if we change this behaviour? With the current utrace-ptrace implementation SIGXXX can be reported to the new tracer. I think there is no application which would handle non-SIGSTOP as the first signal after PTRACE_ATTACH while it would get confused by getting non-SIGSTOP signal as the first one after PTRACE_ATTACH after PTRACE_DETACH. OK, this relates to the first signal should be SIGSTOP but this is wrong anyway, and the case above is very unlikely. If the first signal should be SIGSTOP is not satisfied (current state) I think you can freely change this behavior whether SIGXXX will be reported to the new tracer and we should apply the attached ptrace-testsuite patch. If the first signal should be SIGSTOP gets fixed/satisfied (proposed state) I think it is clear SIGXXX from PTRACE_DETACH must not be lost and it must not be visible as the first signal after PTRACE_ATTACH. In such case the ptrace-testsuite testcase attach-into-signal should be simplified a lot to always just require SIGSTOP as the first signal after PTRACE_ATTACH and the attached change gets irrelevant in such case. Thanks, Jan --- attach-into-signal.c31 Jan 2009 21:11:40 - 1.5 +++ attach-into-signal.c6 Oct 2009 14:27:08 - @@ -224,6 +224,18 @@ static void reproduce (void) child = 0; return; } + /* SIGPIPE was still pending and it has not been yet delivered. */ + if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) +{ + /* Deliver it and get the queued SIGSTOP. */ + errno = 0; + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); + assert_perror (errno); + + errno = 0; + pid = waitpid (child, status, 0); + assert (pid == child); +} assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGSTOP); /* let tracee run. it must be killed very soon by SIGPIPE */
Re: utrace-ptrace detach with signal semantics
On Tue, 06 Oct 2009 19:14:28 +0200, Oleg Nesterov wrote: On 10/06, Jan Kratochvil wrote: [...] If it is not reported to the new tracer then it will be always processed by the tracee, is it right? Yes, sure. (But, just in case... if the tracer does ptrace(DETACH, SIGNR), this signr only matters if the tracee was stopped after reporting syscall or signal, otherwise SIGNR is ignored). In which specific cases SIGNR can get ignored? Whole PTRACE_DETACH will be ignored if the tracee is not stopped. It SIGNR will be proabably ignored if the tracee is now dead. Otherwise SIGNR should get delivered, shouldn't it? + /* SIGPIPE was still pending and it has not been yet delivered. */ + if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) [...] Yes, I didn't verify this yet, but I think with this patch the test-case should succeed with utrace-ptrace kernel. Checked-in. Thanks, Jan
Re: utrace-ptrace detach with signal semantics
On 10/06, Jan Kratochvil wrote: On Tue, 06 Oct 2009 19:14:28 +0200, Oleg Nesterov wrote: On 10/06, Jan Kratochvil wrote: [...] If it is not reported to the new tracer then it will be always processed by the tracee, is it right? Yes, sure. (But, just in case... if the tracer does ptrace(DETACH, SIGNR), this signr only matters if the tracee was stopped after reporting syscall or signal, otherwise SIGNR is ignored). In which specific cases SIGNR can get ignored? Whole PTRACE_DETACH will be ignored if the tracee is not stopped. It SIGNR will be proabably ignored if the tracee is now dead. Otherwise SIGNR should get delivered, shouldn't it? No (afaics). For example, the tracee reports PTRACE_EVENT_EXEC and stops. In this case SIGNR has no effect after PTRACE_CONT/DETACH/etc. SIGNR does not ignored after the tracee reported syscall entry/exit or signal. If you think this should be changed, please tell. As always, I do not know if it was supposed or not. (and in fact I should re-check my understanding after sleep). + /* SIGPIPE was still pending and it has not been yet delivered. */ + if (WIFSTOPPED (status) WSTOPSIG (status) == SIGPIPE) [...] Yes, I didn't verify this yet, but I think with this patch the test-case should succeed with utrace-ptrace kernel. Checked-in. Thanks! Oleg.
Re: utrace-ptrace detach with signal semantics
On Tue, 06 Oct 2009 22:05:16 +0200, Oleg Nesterov wrote: For example, the tracee reports PTRACE_EVENT_EXEC and stops. In this case SIGNR has no effect after PTRACE_CONT/DETACH/etc. SIGNR does not ignored after the tracee reported syscall entry/exit or signal. OK, if only such exceptional cases as PTRACE_EVENT_EXEC that should not matter I think. It should work also for PTRACE_SINGLESTEP. Thanks, Jan
Re: utrace-ptrace detach with signal semantics
On 10/05, Oleg Nesterov wrote: On 10/05, Jan Kratochvil wrote: On Mon, 05 Oct 2009 04:51:32 +0200, Oleg Nesterov wrote: It is not trivial to implement, and I don't understand why it is important to keep this behaviour. But we have the test case which checks this: attach-into-signal. This testcase is in fact PASSing even when non-SIGSTOP signal is sent as the first one after PTRACE_ATTACH. It has specific handling of such cases. This test-case also does: /* detach with SIGPIPE/attach. This should kill tracee */ ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); waitpid (child, status, 0); assert (WIFSIGNALED (status) WTERMSIG (status) == SIGPIPE); It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what I can't understand. Just in case... If I change the test-case --- a/ptrace-tests/tests/attach-into-signal.c 2009-01-31 13:11:40.0 -0800 +++ b/ptrace-tests/tests/attach-into-signal.c 2009-09-20 13:32:30.0 -0700 @@ -225,9 +225,9 @@ static void reproduce (void) return; } assert (WIFSTOPPED (status)); - assert (WSTOPSIG (status) == SIGSTOP); + assert (WSTOPSIG (status) == SIGPIPE); /* let tracee run. it must be killed very soon by SIGPIPE */ - ptrace (PTRACE_CONT, child, (void *) 1, (void *) 0); + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); assert_perror (errno); pid = waitpid (child, status, 0); assert (pid == child); then it doesn't fail. OK. Currently, ptrace(DETACH, SIGXXX) means: - untrace - the tracee will get this SIGXXX and handle this signal - BUT! if the new tracer attaches right now, before the tracee handles the signal, this signal will not be reported to the new tracer. With the current utrace-ptrace implementation: if the second attach happens before the tracee dequeues SIGXXX, this signal will be reported to the new tracer too. So... Jan, do you think this behaviour change can break gdb? Oleg.
utrace-ptrace detach with signal semantics
Jan, Roland, I have the question. Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) and then another/same tracer does ptrace(ATTACH, tracee) then SIGXXX will not be reported to the new tracer. Why? Should utrace-ptrace be 100% compatible here? It is not trivial to implement, and I don't understand why it is important to keep this behaviour. But we have the test case which checks this: attach-into-signal. Could you explain what can be breaked if SIGXXX will be reported to the next tracer (assuming the 2nd ATTACH is fast enough) ? I do not think there is a real life application that does ATTACH + DETACH and relies on fact it must not see this sig. Oleg.