* Any solution to not being able to interrupt step in GDB ?
@ 2008-02-27 22:12 Antony KING
2008-02-27 22:45 ` Daniel Jacobowitz
0 siblings, 1 reply; 6+ messages in thread
From: Antony KING @ 2008-02-27 22:12 UTC (permalink / raw)
To: gdb
I am currently using a version of GDB 6.6 (utilising our own remote
target interface) and I am trying to come up with a solution to the
problem we are seeing with the "step" command.
The problem is that GDB is not making it easy :-) for me to interrupt
the target when a "step" command has been issued on a statement of the
following form:
while (okay) continue;
(where okay is a volatile that will be changed by an interrupt handler).
Please note that the above example is an illustration of a general
problem we encounter when debugging real-time multi-threaded embedded
applications with pre-emptive scheduling and interrupts.
GDB attempts to step the statement but the PC never falls outside the
bounds of the statement address range and so GDB is forever performing a
single instruction step.
As a result I can only interrupt the "step" command when I press Ctrl-C
while GDB executing target_wait(). If Ctrl-C is pressed outside of
target_wait() (which in my implementation provides its own SIGINT
handler), then GDB does not notice the event, as it is stuck in the
following loop in wait_for_inferior() because ecs->wait_some_more is
always TRUE:
while (1)
{
if (deprecated_target_wait_hook)
ecs->ptid = deprecated_target_wait_hook (ecs->waiton_ptid,
ecs->wp);
else
ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp);
/* Now figure out what to do with the result of the result. */
handle_inferior_event (ecs);
if (!ecs->wait_some_more)
break;
}
This means that the user has to continually press Ctrl-C in the hope of
hitting the sweet spot.
Is there any clean solution I can use which allows me to break out this
loop if there is a pending SIGINT event waiting to be processed ? There
seems a be a need for a way to "stop stepping" when Ctrl-C is pressed.
One thought I have is to fake a target SIGINT signal by checking for a
pending SIGINT event after returning from target_wait() and modifying
ecs before calling handle_inferior_event().
Of course the same issue arises when using the MI interface (with, for
example, Eclipse) but is worse since only a single stop request is issued.
[
I have seen that the subject has been raised here:
http://sourceware.org/ml/gdb/2007-03/msg00228.html
but this did not seem to end with a solution.
]
Any advice would be appreciated.
Cheers,
Antony.
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: Any solution to not being able to interrupt step in GDB ? 2008-02-27 22:12 Any solution to not being able to interrupt step in GDB ? Antony KING @ 2008-02-27 22:45 ` Daniel Jacobowitz 2008-02-27 22:46 ` Antony KING 0 siblings, 1 reply; 6+ messages in thread From: Daniel Jacobowitz @ 2008-02-27 22:45 UTC (permalink / raw) To: Antony KING; +Cc: gdb On Wed, Feb 27, 2008 at 09:59:53PM +0000, Antony KING wrote: > Is there any clean solution I can use which allows me to break out this > loop if there is a pending SIGINT event waiting to be processed ? There > seems a be a need for a way to "stop stepping" when Ctrl-C is pressed. > One thought I have is to fake a target SIGINT signal by checking for a > pending SIGINT event after returning from target_wait() and modifying > ecs before calling handle_inferior_event(). I can refer you to the reply to the message you linked; which signal handler is running when not in your "sweet spot"? -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Any solution to not being able to interrupt step in GDB ? 2008-02-27 22:45 ` Daniel Jacobowitz @ 2008-02-27 22:46 ` Antony KING 2008-02-27 22:56 ` Daniel Jacobowitz 0 siblings, 1 reply; 6+ messages in thread From: Antony KING @ 2008-02-27 22:46 UTC (permalink / raw) To: gdb Daniel Jacobowitz wrote: > On Wed, Feb 27, 2008 at 09:59:53PM +0000, Antony KING wrote: >> Is there any clean solution I can use which allows me to break out this >> loop if there is a pending SIGINT event waiting to be processed ? There >> seems a be a need for a way to "stop stepping" when Ctrl-C is pressed. >> One thought I have is to fake a target SIGINT signal by checking for a >> pending SIGINT event after returning from target_wait() and modifying >> ecs before calling handle_inferior_event(). > > I can refer you to the reply to the message you linked; which signal > handler is running when not in your "sweet spot"? > The signal handler is the restored default handler, "handle_sigint". My target interface only substitutes that default SIGINT handler when implementing the target_wait() functionality (it is modelled on remote.c). My first thought was that QUIT should achieve the effect I need but quit_flag, as was pointed out, is not being set soon enough. Also, forcing an immediate_quit is not suitable since I would like to stop the stepping cleanly with a target SIGINT (plus it breaks my target interface, but that is my problem :-). Cheers, Antony ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Any solution to not being able to interrupt step in GDB ? 2008-02-27 22:46 ` Antony KING @ 2008-02-27 22:56 ` Daniel Jacobowitz 2008-02-29 22:09 ` Antony KING 0 siblings, 1 reply; 6+ messages in thread From: Daniel Jacobowitz @ 2008-02-27 22:56 UTC (permalink / raw) To: Antony KING; +Cc: gdb On Wed, Feb 27, 2008 at 10:44:56PM +0000, Antony KING wrote: > The signal handler is the restored default handler, "handle_sigint". My > target interface only substitutes that default SIGINT handler when > implementing the target_wait() functionality (it is modelled on remote.c). > > My first thought was that QUIT should achieve the effect I need but > quit_flag, as was pointed out, is not being set soon enough. Also, > forcing an immediate_quit is not suitable since I would like to stop the > stepping cleanly with a target SIGINT (plus it breaks my target > interface, but that is my problem :-). Why doesn't quit_flag get set? That's how I think we ought to do this. Avoid immediate_quit, that's dangerous to mess with. I'm not sure why you'd want to use a target SIGINT for this case. If we're between steps, we should just make sure we don't send another step. I suppose I hadn't thought about the case between stepping and waiting... -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Any solution to not being able to interrupt step in GDB ? 2008-02-27 22:56 ` Daniel Jacobowitz @ 2008-02-29 22:09 ` Antony KING 2008-02-29 22:49 ` Daniel Jacobowitz 0 siblings, 1 reply; 6+ messages in thread From: Antony KING @ 2008-02-29 22:09 UTC (permalink / raw) To: gdb [-- Attachment #1: Type: text/plain, Size: 2069 bytes --] Daniel Jacobowitz wrote: > On Wed, Feb 27, 2008 at 10:44:56PM +0000, Antony KING wrote: >> The signal handler is the restored default handler, "handle_sigint". My >> target interface only substitutes that default SIGINT handler when >> implementing the target_wait() functionality (it is modelled on remote.c). >> >> My first thought was that QUIT should achieve the effect I need but >> quit_flag, as was pointed out, is not being set soon enough. Also, >> forcing an immediate_quit is not suitable since I would like to stop the >> stepping cleanly with a target SIGINT (plus it breaks my target >> interface, but that is my problem :-). > > Why doesn't quit_flag get set? That's how I think we ought to do > this. Avoid immediate_quit, that's dangerous to mess with. In my grep'ing of the (6.6) sources, I could only find quit_flag being set when async_request_quit() is called, by the event processing loop. It is also set in request_quit() but this API does not seem to be used. > I'm not sure why you'd want to use a target SIGINT for this case. > If we're between steps, we should just make sure we don't send > another step. I suppose I hadn't thought about the case between > stepping and waiting... I was thinking that a target SIGINT notification would be suitable since this is what the user would see if they interrupted a continue; I did not think interrupting a step, from a user perspective, would be any different. Of course, it is a lie since the target did not generate the SIGINT and so this would be confusing, although for the targets I have to support this is not a problem. Also, it was just easier for me to see how to apply a fix without getting too mired in understanding how the target event handling worked in handle_inferior_event() :-) and the mechanics of cleanly stopping. Anyway, I have attached a patch fyi, which is my attempt at providing a solution using a faked target SIGINT which seems to work for me. It is a bit of a bodge since it subverts the main event loop but ce la vie. Cheers, Antony. [-- Attachment #2: stepping-patch.txt --] [-- Type: text/plain, Size: 2841 bytes --] --- event-top.c@@/main/11 2007-07-31 12:22:19.000000000 +0100 +++ event-top.c 2008-02-29 20:37:01.000000000 +0000 @@ -959,6 +959,8 @@ void handle_sigint (int sig) { + extern int in_wait_for_inferior, stop_wait_for_inferior; + signal (sig, handle_sigint); /* If immediate_quit is set, we go ahead and process the SIGINT right @@ -968,8 +970,12 @@ processed only the next time through the event loop. To get to that point, though, the command that we want to interrupt needs to finish first, which is unacceptable. */ + /* However, if currently waiting for the target in wait_for_inferior + just signal wait_for_inferior that a SIGINT is pending. */ if (immediate_quit) async_request_quit (0); + else if (in_wait_for_inferior) + stop_wait_for_inferior = 1; else /* If immediate quit is not set, we process SIGINT the next time through the loop, which is fine. */ --- infrun.c@@/main/12 2007-07-31 12:22:19.000000000 +0100 +++ infrun.c 2008-02-29 20:50:59.000000000 +0000 @@ -99,6 +99,12 @@ fprintf_filtered (file, _("Mode of the step operation is %s.\n"), value); } +/* Set by default SIGINT handler when a SIGINT occurs outside of a + target wait but still waiting for more inferior events. When set + "fake" a SIGINT event when target stops. */ +volatile int stop_wait_for_inferior = 0; +int in_wait_for_inferior = 0; + /* In asynchronous mode, but simulating synchronous execution. */ int sync_execution = 0; @@ -965,6 +971,13 @@ When this function actually returns it means the inferior should be left stopped and GDB should read more commands. */ +static void +wait_for_inferior_cleanup (void *ignore) +{ + in_wait_for_inferior = 0; + delete_step_resume_breakpoint(&step_resume_breakpoint); +} + void wait_for_inferior (void) { @@ -975,8 +988,7 @@ if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: wait_for_inferior\n"); - old_cleanups = make_cleanup (delete_step_resume_breakpoint, - &step_resume_breakpoint); + old_cleanups = make_cleanup (wait_for_inferior_cleanup, 0); /* wfi still stays in a loop, so it's OK just to take the address of a local to get the ecs pointer. */ @@ -998,6 +1010,10 @@ registers_changed (); + /* Reset state. */ + in_wait_for_inferior = 1; + stop_wait_for_inferior = 0; + while (1) { if (deprecated_target_wait_hook) @@ -1005,6 +1021,12 @@ else ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp); + /* Override stop reason if interrupted. */ + if (stop_wait_for_inferior + && (ecs->ws.kind == TARGET_WAITKIND_STOPPED) + && (ecs->ws.value.sig == TARGET_SIGNAL_TRAP)) + ecs->ws.value.sig = TARGET_SIGNAL_INT; + /* Now figure out what to do with the result of the result. */ handle_inferior_event (ecs); ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Any solution to not being able to interrupt step in GDB ? 2008-02-29 22:09 ` Antony KING @ 2008-02-29 22:49 ` Daniel Jacobowitz 0 siblings, 0 replies; 6+ messages in thread From: Daniel Jacobowitz @ 2008-02-29 22:49 UTC (permalink / raw) To: Antony KING; +Cc: gdb On Fri, Feb 29, 2008 at 10:05:44PM +0000, Antony KING wrote: > Daniel Jacobowitz wrote: >> Why doesn't quit_flag get set? That's how I think we ought to do >> this. Avoid immediate_quit, that's dangerous to mess with. > > In my grep'ing of the (6.6) sources, I could only find quit_flag being > set when async_request_quit() is called, by the event processing loop. It > is also set in request_quit() but this API does not seem to be used. Are you working on 6.6 rather than HEAD? Fred Fish moved quit_flag setting from async_request_quit to handle_sigint on 2007-02-09, which is later than your sources. That should simplify things a bit! -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-02-29 22:25 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-02-27 22:12 Any solution to not being able to interrupt step in GDB ? Antony KING 2008-02-27 22:45 ` Daniel Jacobowitz 2008-02-27 22:46 ` Antony KING 2008-02-27 22:56 ` Daniel Jacobowitz 2008-02-29 22:09 ` Antony KING 2008-02-29 22:49 ` Daniel Jacobowitz
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox