On 10/27, Roland McGrath wrote: > > This is used only in the UTRACE_SIGNAL_HANDLER case. That means after > tracehook_signal_handler(), which is where a signal handler has just > been set up. > > For reference, in old ptrace, tracehook_signal_handler() is: > > if (stepping) > ptrace_notify(SIGTRAP); > > This means that when PTRACE_SINGLE{STEP,BLOCK},signr was used to > deliver the handled signal, we stop there in ptrace_notify. This is > in lieu of a proper single-step trap, with the theory that what you > meant to "step to" next was the first instruction of the signal > handler, rather than the second instruction of the handler. > > The only purpose of PTRACE_EVENT_SIGTRAP is to distinguish this case > from PTRACE_EVENT_SIGNAL as it would be for a real SIGTRAP after a > normal instruction step. The only purposes of this distinction are to > make PTRACE_SETSIGINFO have no effect, and to make resumptions ignore > the data/signr argument. The former makes it consistent with other > cases in utrace-ptrace that replace ptrace_notify() calls in the old > ptrace, but that itself is a known nit incompatibility with the old > behavior, so it's superfluous at best. The latter is just intended > for pure bug-compatibility with the old behavior. Aside from these, > there are no other reasons not to have the UTRACE_SIGNAL_HANDLER case > result in PTRACE_EVENT_SIGNAL, with siginfo_t filled in to match what > the old ptrace_notify() does. > > Is that all correct? > > In short, PTRACE_EVENT_SIGTRAP provides bug compatibility for > PTRACE_SINGLESTEP,signr silently acting like PTRACE_SINGLESTEP,0 when
(s/PTRACE_SINGLESTEP/PTRACE_ANY/) > called at the stop just provoked by the last PTRACE_SINGLESTEP,signr. > Is that it? Yes. > I think this is a piece of bug compatibility that upstream will be > happy to have "broken". That is, I bet most people don't realize at > all PTRACE_SINGLESTEP,signr will sometimes swallow a signal after what > appears to be a normal single-step stop. In fact, I suspect many > might say that this is worse than the previous behavior my addition of > this ptrace_notify() call (sometime before git so <2.6.12; Sep 2004, > not sure what version that was, maybe 2.6.9). That behavior was that > PTRACE_SINGLESTEP,signr would stop at the second instruction of the > signal handler and never the first--but that would be a real step > (like you now get after PTRACE_SINGLESTEP,0 when stopped in > ptrace_notify() at the first instruction of the handler). I'm quite > sure that at the time I never contemplated the signal-swallowing > implication of using ptrace_notify() here. > > So, get rid of PTRACE_EVENT_SIGTRAP. Instead for the case of > UTRACE_SIGNAL_HANDLER when stepping, initialize *info to look > like a vanilla SIGTRAP and then fall into the default case for > real signals. Yes, I already thought about this. The patch is trivial, please see below. > Does that all sound right to you, or did I miss something? Don't ask me, I never know what can be changed ;) But yes, I agree. The current behaviour looks strange (if not wrong). With this change ptrace(PTRACE_WHATEVER, signr) after PTRACE_SINGLESTEP never ignores signr. Even if perhaps this is not really useful, this is consistent. Afaics, this case was a single exception when ptrace(signr) or PTRACE_SETSIGINFO) was ignored after PTRACE_SINGLESTEP. The only problem with this change (if we do it now), it is always nice to have a separate changelog to document the behaviour change. But hopefully nobody cares, I mean, nobody will notice the difference. Oleg. --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -73,7 +73,6 @@ struct ptrace_context { #define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) #define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) -#define PTRACE_EVENT_SIGTRAP (3 << 16) #define PTRACE_EVENT_SIGNAL (4 << 16) /* events visible to user-space */ #define PTRACE_EVENT_MASK 0xFFFF @@ -495,8 +494,8 @@ static u32 ptrace_report_signal(u32 acti context->siginfo = NULL; if (resume != UTRACE_RESUME) { - set_stop_code(context, PTRACE_EVENT_SIGTRAP); - return UTRACE_STOP | UTRACE_SIGNAL_IGN; + info->si_signo = SIGTRAO; + break; } case UTRACE_SIGNAL_REPORT: @@ -509,21 +508,21 @@ static u32 ptrace_report_signal(u32 acti return resume | resume_signal(task, context->signr, info, return_ka); - default: - WARN_ON(context->siginfo); - context->siginfo = info; - /* - * context->siginfo points to the caller's stack. - * Make sure the subsequent UTRACE_SIGNAL_REPORT clears - * ->siginfo before return from get_signal_to_deliver(). - */ - utrace_control(task, engine, UTRACE_INTERRUPT); + } - context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; - context->signr = info->si_signo; + WARN_ON(context->siginfo); + context->siginfo = info; + /* + * context->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ + utrace_control(task, engine, UTRACE_INTERRUPT); - return UTRACE_STOP | UTRACE_SIGNAL_IGN; - } + context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; + context->signr = info->si_signo; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; } static u32 ptrace_report_quiesce(u32 action,