Discussion:
What happened in gdb between handle_sigint and async_request_quit?
Amker.Cheng
2009-02-05 12:31:45 UTC
Permalink
HI All:
It's my first message in this list. Please be generous if I break any
rules unintentionally.

I am studying gdb internals by debugging with native gdb-6.8 under
winxp_Sp2+cygwin-5.1,
and trying to find out how gdb handles signals, for example, hitting
Ctrol+c during debugging.


In my view, gdb registers "handle_sigint" to SIGINT in function
"async_init_signals" at first,
then creates async_signal_handler with "proc=async_request_quit" for
"sigint_token", here comes the codes:

void
async_init_signals (void)
{
signal (SIGINT, handle_sigint);
sigint_token =
create_async_signal_handler (async_request_quit, NULL);

/*other codes*/
}

void
handle_sigint (int sig)
{
signal (sig, handle_sigint);

/* We could be running in a loop reading in symfiles or something so
it may be quite a while before we get back to the event loop. So
set quit_flag to 1 here. Then if QUIT is called before we get to
the event loop, we will unwind as expected. */

quit_flag = 1;

/* If immediate_quit is set, we go ahead and process the SIGINT right
away, even if we usually would defer this to the event loop. The
assumption here is that it is safe to process ^C immediately if
immediate_quit is set. If we didn't, SIGINT would be really
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. */
if (immediate_quit)
async_request_quit (0);
else
/* If immediate quit is not set, we process SIGINT the next time
through the loop, which is fine. */
mark_async_signal_handler_wrapper (sigint_token);
}
---------------cut here---------------

It's clear that in "handle_sigint" it just marks the corresponding
async_signal_handler of SIGINT,
result in the true SIGNAL HANDLER "async_request_quit" will be called
during next event loop.

I think gdb must stops the debuggee between calling to "handle_sigint"
and "async_request_quit",
the question is I cannot locate the codes doing this work.

Also, "handle_sigint" set "quit_flag" to 1, but I traced gdb and found
that it was set back to 0
before "async_request_quit" invoked. Who did this and when?

It seems to me that the asynchronous event loop is hard to trace, does
anybody have any tips?

Thanks in advance.
Best Regards.
teawater
2009-02-05 16:12:49 UTC
Permalink
I think your mean that you want know how to stop running inferior with
ctrl-c in GDB, right?

I think:
The handler that your talk about it's not about how to stop running inferior.

For most of host debug, when you put ctrl-c. System will send SIGINT
to inferior. Then inferior stop and gdb handler it. It will deal with
this sig according to "info signals".

For example, you can use command "handle SIGINT nostop print nopass",
after that. ctrl-c will not stop inferior.
Of course, I just try it in linux.

In some other target, it will have special way to handler it. For
example, remote target. It handler sig with itself.


Hui
Post by Amker.Cheng
It's my first message in this list. Please be generous if I break any
rules unintentionally.
I am studying gdb internals by debugging with native gdb-6.8 under
winxp_Sp2+cygwin-5.1,
and trying to find out how gdb handles signals, for example, hitting
Ctrol+c during debugging.
In my view, gdb registers "handle_sigint" to SIGINT in function
"async_init_signals" at first,
then creates async_signal_handler with "proc=async_request_quit" for
void
async_init_signals (void)
{
signal (SIGINT, handle_sigint);
sigint_token =
create_async_signal_handler (async_request_quit, NULL);
/*other codes*/
}
void
handle_sigint (int sig)
{
signal (sig, handle_sigint);
/* We could be running in a loop reading in symfiles or something so
it may be quite a while before we get back to the event loop. So
set quit_flag to 1 here. Then if QUIT is called before we get to
the event loop, we will unwind as expected. */
quit_flag = 1;
/* If immediate_quit is set, we go ahead and process the SIGINT right
away, even if we usually would defer this to the event loop. The
assumption here is that it is safe to process ^C immediately if
immediate_quit is set. If we didn't, SIGINT would be really
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. */
if (immediate_quit)
async_request_quit (0);
else
/* If immediate quit is not set, we process SIGINT the next time
through the loop, which is fine. */
mark_async_signal_handler_wrapper (sigint_token);
}
---------------cut here---------------
It's clear that in "handle_sigint" it just marks the corresponding
async_signal_handler of SIGINT,
result in the true SIGNAL HANDLER "async_request_quit" will be called
during next event loop.
I think gdb must stops the debuggee between calling to "handle_sigint"
and "async_request_quit",
the question is I cannot locate the codes doing this work.
Also, "handle_sigint" set "quit_flag" to 1, but I traced gdb and found
that it was set back to 0
before "async_request_quit" invoked. Who did this and when?
It seems to me that the asynchronous event loop is hard to trace, does
anybody have any tips?
Thanks in advance.
Best Regards.
paawan oza
2009-02-05 16:24:53 UTC
Permalink
Hi Amker,

I think what you have understood it not so accurate.
you have assumed, that handle_sigint is the sigint handler all the time.
no, it is not like that completely, as far as I know.

when gdb has prompt, of course handle_sigint is the handler.
but when gdb is waiting for signals from inferior, pass_signal becomes new handler, which passes SIGINT to the process.

Did I udnerstand you correctly ?

Regards,
..Paawan.
Subject: Re: What happened in gdb between handle_sigint and async_request_quit?
Date: Thursday, February 5, 2009, 9:42 PM
I think your mean that you want know how to stop running
inferior with
ctrl-c in GDB, right?
The handler that your talk about it's not about how to
stop running inferior.
For most of host debug, when you put ctrl-c. System will
send SIGINT
to inferior. Then inferior stop and gdb handler it. It
will deal with
this sig according to "info signals".
For example, you can use command "handle SIGINT nostop
print nopass",
after that. ctrl-c will not stop inferior.
Of course, I just try it in linux.
In some other target, it will have special way to handler
it. For
example, remote target. It handler sig with itself.
Hui
On Thu, Feb 5, 2009 at 20:31, Amker.Cheng
Post by Amker.Cheng
It's my first message in this list. Please be
generous if I break any
Post by Amker.Cheng
rules unintentionally.
I am studying gdb internals by debugging with native
gdb-6.8 under
Post by Amker.Cheng
winxp_Sp2+cygwin-5.1,
and trying to find out how gdb handles signals, for
example, hitting
Post by Amker.Cheng
Ctrol+c during debugging.
In my view, gdb registers "handle_sigint" to
SIGINT in function
Post by Amker.Cheng
"async_init_signals" at first,
then creates async_signal_handler with
"proc=async_request_quit" for
Post by Amker.Cheng
void
async_init_signals (void)
{
signal (SIGINT, handle_sigint);
sigint_token =
create_async_signal_handler (async_request_quit,
NULL);
Post by Amker.Cheng
/*other codes*/
}
void
handle_sigint (int sig)
{
signal (sig, handle_sigint);
/* We could be running in a loop reading in symfiles
or something so
Post by Amker.Cheng
it may be quite a while before we get back to the
event loop. So
Post by Amker.Cheng
set quit_flag to 1 here. Then if QUIT is called
before we get to
Post by Amker.Cheng
the event loop, we will unwind as expected. */
quit_flag = 1;
/* If immediate_quit is set, we go ahead and process
the SIGINT right
Post by Amker.Cheng
away, even if we usually would defer this to the
event loop. The
Post by Amker.Cheng
assumption here is that it is safe to process ^C
immediately if
Post by Amker.Cheng
immediate_quit is set. If we didn't, SIGINT
would be really
Post by Amker.Cheng
processed only the next time through the event
loop. To get to
Post by Amker.Cheng
that point, though, the command that we want to
interrupt needs to
Post by Amker.Cheng
finish first, which is unacceptable. */
if (immediate_quit)
async_request_quit (0);
else
/* If immediate quit is not set, we process SIGINT
the next time
Post by Amker.Cheng
through the loop, which is fine. */
mark_async_signal_handler_wrapper (sigint_token);
}
---------------cut here---------------
It's clear that in "handle_sigint" it
just marks the corresponding
Post by Amker.Cheng
async_signal_handler of SIGINT,
result in the true SIGNAL HANDLER
"async_request_quit" will be called
Post by Amker.Cheng
during next event loop.
I think gdb must stops the debuggee between calling to
"handle_sigint"
Post by Amker.Cheng
and "async_request_quit",
the question is I cannot locate the codes doing this
work.
Post by Amker.Cheng
Also, "handle_sigint" set
"quit_flag" to 1, but I traced gdb and found
Post by Amker.Cheng
that it was set back to 0
before "async_request_quit" invoked. Who did
this and when?
Post by Amker.Cheng
It seems to me that the asynchronous event loop is
hard to trace, does
Post by Amker.Cheng
anybody have any tips?
Thanks in advance.
Best Regards.
Amker.Cheng
2009-02-06 09:14:51 UTC
Permalink
Hi:
Thank both of you. I try to make it clear in this relative long
message. Thanks for your time.

To teawater:
Sorry for my poor English which misdirected you. I want to kown how
gdb handles signals.

To Paawan:
I checked the source and found what you said is the case for linux native debug.
However, I will focus on host debug under win32+cygwin form now on.

In this case I did not find where gdb reset HANDLER for signal
SIGINT(with "win32_wait" checked especially),
so I think that handle_sigint is the SIGINT handler when GDB is
waiting for debug events from inferior.

To make sure of this, I added following fprintf codes at several
locations in GDB:

print codes:
fprintf(stdout, "\n%4d : OUTPUT : begin wait %s:%s:%d\n",
print_times++, __FILE__, __FUNCTION__, __LINE__);
----------------------codes cut here---------------------

locations:
1 : before and after calling to Function "WaitForDebugEvent" in
Function "get_win32_debug_event";
2 : at the beginning of Function "win32_resume";
3 : at the beginning of Function "win32_stop";
4 : at DBG_CONTROL_C case branch in Function "handle_exceptions";
5 : at the beginning of Function "handle_sigint";
----------------------locations cut here---------------------



Then I tested following program:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

int flags = 1;
void func(int sig)
{
fprintf(stdout, "\tget SIGINT, exit the loop.\n");
flags = 0;
}
int main(void)
{
fprintf(stdout, "\tsetup func for SIGINT.\n");
(void)signal (SIGINT, func);
fprintf(stdout, "\tstart infinite loop.\n");
while(1 == flags) ;

fprintf(stdout, "\tdone.\n");
return 0;
}
----------------------program cut here---------------------

when debuggee is running the infinite loop I pressed "CTRL+C" and
"continue" one by one from gdb command line.
Then I got following outputs:


GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-pc-cygwin"...
(gdb) r
Starting program: /cygdrive/e/work/gdb/native-target/bin/dummy3.exe

0 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

1 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307
[New thread 8248.0x51e0]

2 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

3 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

4 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

5 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

6 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

7 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

8 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

9 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

10 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

11 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

12 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

13 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

14 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

15 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

16 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

17 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

18 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

19 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

20 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

21 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

22 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307
[New thread 8248.0x32b0]

23 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

24 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

25 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

26 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

27 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

28 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

29 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

30 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

31 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

32 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

33 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

34 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

35 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

36 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

37 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

38 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

39 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

40 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

41 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

42 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

43 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

44 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

45 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

46 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

47 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

48 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

49 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

50 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

51 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

52 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

<--------------------------------------------------------"CTRL+C" hit

53 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307
[New thread 8248.0x29a4]

54 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

55 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

56 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

57 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:handle_exception:1080

Program received signal SIGINT, Interrupt.

58 : OUTPUT : ../../gdb-6.8/gdb/event-top.c:handle_sigint:964
[Switching to thread 8248.0x29a4]
0x7c874fed in KERNEL32!GetConsoleCharType ((gdb)
59 : OUTPUT : ../../gdb-6.8/gdb/event-top.c:async_request_quit:1010
c
Continuing.

60 : OUTPUT : ../../gdb-6.8/gdb/win32-nat.c:win32_resume:1197

61 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299

62 : OUTPUT : end wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1307

63 : OUTPUT : begin wait
../../gdb-6.8/gdb/win32-nat.c:get_win32_debug_event:1299
-----------------------outputs cut here---------------------

according to above outputs, here are some facts.

1 : OUTPUT 58 and 59 prove that the handler for SIGINT is
handle_sigint when gdb is waiting for inferior's debug events.

2 : OUTPUT 57 is printed in Function handle_exception because (words
from MS MSDN):
"Windows generates a DBG_CONTROL_C exception code when "CTROL+C" is
input to a console process
that handles ctrl+c signals and is being debugged."

please refer to
"http://msdn.microsoft.com/en-us/library/ms679302(VS.85).aspx" for
more.

3 : I noticed that Function "win32_stop" wasn't invoked because of no
corresponding printed info.

4 : Function "handle_exception" is invoked before "handle_sigint" in
this test, though it was invoked
after Function "handle_sigint" sometimes in other tests.

Now comes the puzzle:
In the end, which one sends CTROL+C to debuggee, GDB or Windows?

If it is GDB, where does it do this(apparently not in Function "win32_stop")?
If it is Windows, It would be conflit with what I've already sensed as
well as the view of
lots of messages I've googled. as following one from Pedro Alves:
http://www.cygwin.com/ml/cygwin/2007-03/msg00123.html

PS : I changed the timeout for "WaitForDebugEvent" from 1 second to a
much longer time
in order to get rid of lots useless OUTPUT in "get_win32_debug_event"
because of timeout.

Regards.
Post by paawan oza
Hi Amker,
I think what you have understood it not so accurate.
you have assumed, that handle_sigint is the sigint handler all the time.
no, it is not like that completely, as far as I know.
when gdb has prompt, of course handle_sigint is the handler.
but when gdb is waiting for signals from inferior, pass_signal becomes new handler, which passes SIGINT to the process.
Did I udnerstand you correctly ?
Regards,
..Paawan.
Amker.Cheng
2009-02-06 15:14:26 UTC
Permalink
Hi :
I think I've got the truth about what happened when CTRL+C is hit
during debugging.

both of GDB and Debuggee will get the event. Windows will report DBG_CONTROL_C
exception to GDB, which was turned into TARGET_SIGNAL_INT in GDB.
According to MSDN, this is the First Chance Exception!

Now the debugee is stopped and GDB got informed.

After I input the "continue" command .
Because the default action is nopass for SIGINT, GDB will just resume
debuggee using
function ContinueDebugEvent() with the second argument set to DBG_CONTINUE,
which stops all exception processing and continues the
thread(debuggee). That's why
debuggee will not get the CTRL+C event. To be accurate, the debuggee
has received
the CTRL+C event, just bypassed by OS violently.

Again, if I let GDB pass SIGINT to debuggee using command "handle 2 pass",
GDB will call function ContinueDebugEvent() with the second argument set to
DBG_EXCEPTION_NOT_HANDLED, which cause debuggee to continues the
exception processing(for this is a first-chance exception event).

Now I think it clear enough as how GDB handles SIGINT is concerned, am I right?
Although there are other puzzles such as the "quit_flag", etc..

Thanks for your time
Regards.
Joel Brobecker
2009-02-06 16:42:54 UTC
Permalink
Post by Amker.Cheng
both of GDB and Debuggee will get the event. Windows will report DBG_CONTROL_C
exception to GDB, which was turned into TARGET_SIGNAL_INT in GDB.
According to MSDN, this is the First Chance Exception!
The situation on Windows is different from the situation on Unix.
On Unix, we give the terminal back to the inferior while the inferior
is running. So, when a user presses Ctrl-c, only the inferior gets
the signal. This signal triggers a debug event to GDB and suspends
the inferior, and GDB treats this signal as it would treat any other
signal. On Windows, things are a little trickier, because the inferior
and GDB might be running in the same console. This means that, when
the user presses Ctrl-c, then *both* GDB and the inferior get the
associated signal. But we don't actually want GDB to receive the signal,
so we simply temporarily ignore all Ctrl-C signals in GDB while the
inferior is waiting:

/* Ignore CTRL+C signals while waiting for a debug event.
FIXME: brobecker/2008-05-20: When the user presses CTRL+C while
the inferior is running, both the inferior and GDB receive the
associated signal. If the inferior receives the signal first
and the delay until GDB receives that signal is sufficiently long,
GDB can sometimes receive the SIGINT after we have unblocked
the CTRL+C handler. This would lead to the debugger to stop
prematurely while handling the new-thread event that comes
with the handling of the SIGINT inside the inferior, and then
stop again immediately when the user tries to resume the execution
in the inferior. This is a classic race, and it would be nice
to find a better solution to that problem. But in the meantime,
the current approach already greatly mitigate this issue. */
SetConsoleCtrlHandler (NULL, TRUE);
retval = get_windows_debug_event (pid, ourstatus);
SetConsoleCtrlHandler (NULL, FALSE);

The code above assumes that the inferior and GDB are running in
the same console, which is not always the case. Currently, when
this is the case, the only way to interrupt your program is by
pressing Ctrl-c in the console where your program is running.
There is patch pending that enhances GDB to handle the case when
the inferior is running in a separate console.
--
Joel
Amker.Cheng
2009-02-07 10:08:15 UTC
Permalink
Hi Joel:
Thanks for the detailed explanation, It's very helpful.
The patch you mentioned was applied after the release of version 6.8,
I was wondering then why GDB stops twice at a great probability when
one CTRL+C being hit.

But one more question, where GDB blocks CTRL+C handler? I was thinking
that the handler
"handle_sigint" is always registered during waiting for inferior's event.

Thanks a lot.
Regards.
Post by Joel Brobecker
Post by Amker.Cheng
both of GDB and Debuggee will get the event. Windows will report DBG_CONTROL_C
exception to GDB, which was turned into TARGET_SIGNAL_INT in GDB.
According to MSDN, this is the First Chance Exception!
The situation on Windows is different from the situation on Unix.
On Unix, we give the terminal back to the inferior while the inferior
is running. So, when a user presses Ctrl-c, only the inferior gets
the signal. This signal triggers a debug event to GDB and suspends
the inferior, and GDB treats this signal as it would treat any other
signal. On Windows, things are a little trickier, because the inferior
and GDB might be running in the same console. This means that, when
the user presses Ctrl-c, then *both* GDB and the inferior get the
associated signal. But we don't actually want GDB to receive the signal,
so we simply temporarily ignore all Ctrl-C signals in GDB while the
/* Ignore CTRL+C signals while waiting for a debug event.
FIXME: brobecker/2008-05-20: When the user presses CTRL+C while
the inferior is running, both the inferior and GDB receive the
associated signal. If the inferior receives the signal first
and the delay until GDB receives that signal is sufficiently long,
GDB can sometimes receive the SIGINT after we have unblocked
the CTRL+C handler. This would lead to the debugger to stop
prematurely while handling the new-thread event that comes
with the handling of the SIGINT inside the inferior, and then
stop again immediately when the user tries to resume the execution
in the inferior. This is a classic race, and it would be nice
to find a better solution to that problem. But in the meantime,
the current approach already greatly mitigate this issue. */
SetConsoleCtrlHandler (NULL, TRUE);
retval = get_windows_debug_event (pid, ourstatus);
SetConsoleCtrlHandler (NULL, FALSE);
The code above assumes that the inferior and GDB are running in
the same console, which is not always the case. Currently, when
this is the case, the only way to interrupt your program is by
pressing Ctrl-c in the console where your program is running.
There is patch pending that enhances GDB to handle the case when
the inferior is running in a separate console.
--
Joel
Loading...