stepi/nexti: skip signal handler if "handle nostop" signal arrives
authorPedro Alves <palves@redhat.com>
Mon, 27 Oct 2014 20:24:59 +0000 (20:24 +0000)
committerPedro Alves <palves@redhat.com>
Mon, 27 Oct 2014 20:26:12 +0000 (20:26 +0000)
commite5f8a7cc2d376c81749b6e4a4efc034201cf683c
treedde215ef253ca851fe7fa3ee9e2d849a1e211b06
parentbf67003b4567600ed3022a439207ac8f26454f91
stepi/nexti: skip signal handler if "handle nostop" signal arrives

I noticed that "si" behaves differently when a "handle nostop" signal
arrives while the step is in progress, depending on whether the
program was stopped at a breakpoint when "si" was entered.
Specifically, in case GDB needs to step off a breakpoint, the handler
is skipped and the program stops in the next "mainline" instruction.
Otherwise, the "si" stops in the first instruction of the signal
handler.

I was surprised the testsuite doesn't catch this difference.  Turns
out gdb.base/sigstep.exp covers a bunch of cases related to stepping
and signal handlers, but does not test stepi nor nexti, only
step/next/continue.

My first reaction was that stopping in the signal handler was the
correct thing to do, as it's where the next user-visible instruction
that is executed is.  I considered then "nexti" -- a signal handler
could be reasonably considered a subroutine call to step over, it'd
seem intuitive to me that "nexti" would skip it.

But then, I realized that signals that arrive while a plain/line
"step" is in progress _also_ have their handler skipped.  A user might
well be excused for being confused by this, given:

  (gdb) help step
  Step program until it reaches a different source line.

And the signal handler's sources will be in different source lines,
after all.

I think that having to explain that "stepi" steps into handlers, (and
that "nexti" wouldn't according to my reasoning above), while "step"
does not, is a sign of an awkward interface.

E.g., if a user truly is interested in stepping into signal handlers,
then it's odd that she has to either force the signal to "handle
stop", or recall to do "stepi" whenever such a signal might be
delivered.  For that use case, it'd seem nicer to me if "step" also
stepped into handlers.

This suggests to me that we either need a global "step-into-handlers"
setting, or perhaps better, make "handle pass/nopass stop/nostop
print/noprint" have have an additional axis - "handle
stepinto/nostepinto", so that the user could configure whether
handlers for specific signals should be stepped into.

In any case, I think it's simpler (and thus better) for all step
commands to behave the same.  This commit thus makes "si/ni" skip
handlers for "handle nostop" signals that arrive while the command was
already in progress, like step/next do.

To be clear, nothing changes if the program was stopped for a signal,
and the user enters a stepping command _then_ -- GDB still steps into
the handler.  The change concerns signals that don't cause a stop and
that arrive while the step is in progress.

Tested on x86_64 Fedora 20, native and gdbserver.

gdb/
2014-10-27  Pedro Alves  <palves@redhat.com>

* infrun.c (handle_signal_stop): Also skip handlers when a random
signal arrives while handling a "stepi" or a "nexti".  Set the
thread's 'step_after_step_resume_breakpoint' flag.

gdb/doc/
2014-10-27  Pedro Alves  <palves@redhat.com>

* gdb.texinfo (Continuing and Stepping): Add cross reference to
info on stepping and signal handlers.
(Signals): Explain stepping and signal handlers.  Add context
index entry, and cross references.

gdb/testsuite/
2014-10-27  Pedro Alves  <palves@redhat.com>

* gdb.base/sigstep.c (dummy): New global.
(main): Issue a couple writes to the new global.
* gdb.base/sigstep.exp (get_next_pc, test_skip_handler): New
procedures.
(skip_over_handler): Use test_skip_handler.
(top level): Call skip_over_handler for stepi and nexti too.
(breakpoint_over_handler): Use test_skip_handler.
(top level): Call breakpoint_over_handler for stepi and nexti too.
gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/infrun.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/sigstep.c
gdb/testsuite/gdb.base/sigstep.exp