diff options
Diffstat (limited to 'gdb/event-top.c')
-rw-r--r-- | gdb/event-top.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/gdb/event-top.c b/gdb/event-top.c index 2f0a758..eef1514 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -38,6 +38,8 @@ #include "annotate.h" #include "maint.h" #include "buffer.h" +#include "ser-event.h" +#include "gdb_select.h" /* readline include files. */ #include "readline/readline.h" @@ -733,6 +735,12 @@ gdb_readline_no_editing_callback (gdb_client_data client_data) } +/* The serial event associated with the QUIT flag. set_quit_flag sets + this, and check_quit_flag clears it. Used by interruptible_select + to be able to do interruptible I/O with no race with the SIGINT + handler. */ +static struct serial_event *quit_serial_event; + /* Initialization of signal handlers and tokens. There is a function handle_sig* for each of the signals GDB cares about. Specifically: SIGINT, SIGFPE, SIGQUIT, SIGTSTP, SIGHUP, SIGWINCH. These @@ -750,6 +758,8 @@ async_init_signals (void) { initialize_async_signal_handlers (); + quit_serial_event = make_serial_event (); + signal (SIGINT, handle_sigint); sigint_token = create_async_signal_handler (async_request_quit, NULL); @@ -794,8 +804,33 @@ async_init_signals (void) #endif } -/* Tell the event loop what to do if SIGINT is received. - See event-signal.c. */ +/* See defs.h. */ + +void +quit_serial_event_set (void) +{ + serial_event_set (quit_serial_event); +} + +/* See defs.h. */ + +void +quit_serial_event_clear (void) +{ + serial_event_clear (quit_serial_event); +} + +/* Return the selectable file descriptor of the serial event + associated with the quit flag. */ + +static int +quit_serial_event_fd (void) +{ + return serial_event_fd (quit_serial_event); +} + +/* Handle a SIGINT. */ + void handle_sigint (int sig) { @@ -819,6 +854,42 @@ handle_sigint (int sig) gdb_call_async_signal_handler (sigint_token, immediate_quit); } +/* See gdb_select.h. */ + +int +interruptible_select (int n, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + fd_set my_readfds; + int fd; + int res; + + if (readfds == NULL) + { + readfds = &my_readfds; + FD_ZERO (&my_readfds); + } + + fd = quit_serial_event_fd (); + FD_SET (fd, readfds); + if (n <= fd) + n = fd + 1; + + do + { + res = gdb_select (n, readfds, writefds, exceptfds, timeout); + } + while (res == -1 && errno == EINTR); + + if (res == 1 && FD_ISSET (fd, readfds)) + { + errno = EINTR; + return -1; + } + return res; +} + /* Handle GDB exit upon receiving SIGTERM if target_can_async_p (). */ static void |