target remote: Don't rely on immediate_quit (introduce quit handlers)

remote.c is the last user of immediate_quit.  It's relied on to
immediately break the initial remote connection sync up, if the user
does Ctrl-C, assuming that was because the target isn't responding.
At that stage, since the connection isn't synced yet, disconnecting is
the only safe thing to do.  This commit reworks that, to not rely on
throwing from the SIGINT signal handler.

So, this commit:

- Introduces the concept of a "quit handler".  This is used to
  override what does the QUIT macro do when the quit flag is set.

- Makes the "struct serial" reachar / write code call QUIT in the
  partial read/write loops, so the current quit handler is invoked
  whenever a serial->read_prim / serial->write_prim returns EINTR.

- Makes the "struct serial" reachar / write code call
  interruptible_select instead of gdb_select, so that QUITs are
  detected in a race-free manner.

- Stops remote.c from setting immediate_quit during the initial
  connection.

- Instead, we install a custom quit handler whenever we're calling
  into the serial code.  This custom quit handler knows to immediately
  throw a quit when we're in the initial connection setup, and
  otherwise defer handling the quit/Ctrl-C request to later, when
  we're safely out of a packet command/response sequence.  This also
  is what is now responsible for handling "double Ctrl-C because
  target connection is stuck/wedged."

- remote.c no longer installs a specialized SIGINT handlers, and
  instead re-uses the quit flag.  Since we want to rely on the QUIT
  macro, the SIGINT handler must also set the quit.  And the easiest
  is just to not install custom SIGINT handler in remote.c.  Let the
  standard SIGINT handler do its job of setting the quit flag.
  Centralizing SIGINT handlers seems like a good thing to me, anyway.

gdb/ChangeLog:
2016-04-12  Pedro Alves  <palves@redhat.com>

	* defs.h (quit_handler_ftype, quit_handler)
	(make_cleanup_override_quit_handler, default_quit_handler): New.
	(QUIT): Adjust comments.
	* event-top.c (default_quit_handler): New function.
	(quit_handler): New global.
	(struct quit_handler_cleanup_data): New.
	(restore_quit_handler, restore_quit_handler_dtor)
	(make_cleanup_override_quit_handler): New.
	(async_request_quit): Call QUIT.
	* remote.c (struct remote_state) <got_ctrlc_during_io>: New field.
	(async_sigint_remote_twice_token, async_sigint_remote_token):
	Delete.
	(remote_close): Update comments.
	(remote_start_remote): Don't set immediate_quit.  Set starting_up
	earlier.
	(remote_serial_quit_handler, remote_unpush_and_throw): New
	functions.
	(remote_open_1): Clear got_ctrlc_during_io.  Set
	remote_async_terminal_ours_p unconditionally.
	(async_initialize_sigint_signal_handler)
	(async_handle_remote_sigint, async_handle_remote_sigint_twice)
	(remote_check_pending_interrupt, async_remote_interrupt)
	(async_remote_interrupt_twice)
	(async_cleanup_sigint_signal_handler, ofunc)
	(sync_remote_interrupt, sync_remote_interrupt_twice): Delete.
	(remote_terminal_inferior, remote_terminal_ours): Remove async
	checks.
	(remote_wait_as): Don't install a SIGINT handler in sync mode.
	(readchar, remote_serial_write): Override the quit handler with
	remote_serial_quit_handler.
	(getpkt_or_notif_sane_1): Don't call QUIT.
	(initialize_remote_ops): Don't install
	remote_check_pending_interrupt.
	(_initialize_remote): Don't create async_sigint_remote_token and
	async_sigint_remote_twice_token.
	* ser-base.c (ser_base_wait_for): Call QUIT and use
	interruptible_select.
	(ser_base_write): Call QUIT.
	* ser-go32.c (dos_readchar, dos_write): Call QUIT.
	* ser-unix.c (wait_for): Don't use VTIME.  Always take the
	gdb_select path, but call QUIT and interruptible_select.
	* utils.c (maybe_quit): Call the current quit handler.  Don't call
	target_check_pending_interrupt.
	(defaulted_query, prompt_for_continue): Override the quit handler
	with the default quit handler.
This commit is contained in:
Pedro Alves 2016-04-12 16:49:32 +01:00
parent a12ac51333
commit 048094accc
8 changed files with 285 additions and 254 deletions

View File

@ -1,3 +1,51 @@
2016-04-12 Pedro Alves <palves@redhat.com>
* defs.h (quit_handler_ftype, quit_handler)
(make_cleanup_override_quit_handler, default_quit_handler): New.
(QUIT): Adjust comments.
* event-top.c (default_quit_handler): New function.
(quit_handler): New global.
(struct quit_handler_cleanup_data): New.
(restore_quit_handler, restore_quit_handler_dtor)
(make_cleanup_override_quit_handler): New.
(async_request_quit): Call QUIT.
* remote.c (struct remote_state) <got_ctrlc_during_io>: New field.
(async_sigint_remote_twice_token, async_sigint_remote_token):
Delete.
(remote_close): Update comments.
(remote_start_remote): Don't set immediate_quit. Set starting_up
earlier.
(remote_serial_quit_handler, remote_unpush_and_throw): New
functions.
(remote_open_1): Clear got_ctrlc_during_io. Set
remote_async_terminal_ours_p unconditionally.
(async_initialize_sigint_signal_handler)
(async_handle_remote_sigint, async_handle_remote_sigint_twice)
(remote_check_pending_interrupt, async_remote_interrupt)
(async_remote_interrupt_twice)
(async_cleanup_sigint_signal_handler, ofunc)
(sync_remote_interrupt, sync_remote_interrupt_twice): Delete.
(remote_terminal_inferior, remote_terminal_ours): Remove async
checks.
(remote_wait_as): Don't install a SIGINT handler in sync mode.
(readchar, remote_serial_write): Override the quit handler with
remote_serial_quit_handler.
(getpkt_or_notif_sane_1): Don't call QUIT.
(initialize_remote_ops): Don't install
remote_check_pending_interrupt.
(_initialize_remote): Don't create async_sigint_remote_token and
async_sigint_remote_twice_token.
* ser-base.c (ser_base_wait_for): Call QUIT and use
interruptible_select.
(ser_base_write): Call QUIT.
* ser-go32.c (dos_readchar, dos_write): Call QUIT.
* ser-unix.c (wait_for): Don't use VTIME. Always take the
gdb_select path, but call QUIT and interruptible_select.
* utils.c (maybe_quit): Call the current quit handler. Don't call
target_check_pending_interrupt.
(defaulted_query, prompt_for_continue): Override the quit handler
with the default quit handler.
2016-04-12 Pedro Alves <palves@redhat.com>
* tui/tui-hooks.c (tui_target_has_run): Delete.

View File

@ -145,6 +145,34 @@ extern int check_quit_flag (void);
/* * Set the quit flag. */
extern void set_quit_flag (void);
/* The current quit handler (and its type). This is called from the
QUIT macro. See default_quit_handler below for default behavior.
Parts of GDB temporarily override this to e.g., completely suppress
Ctrl-C because it would not be safe to throw. E.g., normally, you
wouldn't want to quit between a RSP command and its response, as
that would break the communication with the target, but you may
still want to intercept the Ctrl-C and offer to disconnect if the
user presses Ctrl-C multiple times while the target is stuck
waiting for the wedged remote stub. */
typedef void (quit_handler_ftype) (void);
extern quit_handler_ftype *quit_handler;
/* Override the current quit handler. Sets NEW_QUIT_HANDLER as
current quit handler, and installs a cleanup that when run restores
the previous quit handler. */
struct cleanup *
make_cleanup_override_quit_handler (quit_handler_ftype *new_quit_handler);
/* The default quit handler. Checks whether Ctrl-C was pressed, and
if so:
- If GDB owns the terminal, throws a quit exception.
- If GDB does not own the terminal, forwards the Ctrl-C to the
target.
*/
extern void default_quit_handler (void);
/* Flag that function quit should call quit_force. */
extern volatile int sync_quit_force_run;
@ -156,10 +184,8 @@ extern void quit (void);
extern void maybe_quit (void);
/* Check whether a Ctrl-C was typed, and if so, call quit. The target
is given a chance to process the Ctrl-C. E.g., it may detect that
repeated Ctrl-C requests were issued, and choose to close the
connection. */
/* Check whether a Ctrl-C was typed, and if so, call the current quit
handler. */
#define QUIT maybe_quit ()
/* Set the serial event associated with the quit flag. */

View File

@ -828,6 +828,68 @@ quit_serial_event_fd (void)
return serial_event_fd (quit_serial_event);
}
/* See defs.h. */
void
default_quit_handler (void)
{
if (check_quit_flag ())
{
if (target_terminal_is_ours ())
quit ();
else
target_pass_ctrlc ();
}
}
/* See defs.h. */
quit_handler_ftype *quit_handler = default_quit_handler;
/* Data for make_cleanup_override_quit_handler. Wrap the previous
handler pointer in a data struct because it's not portable to cast
a function pointer to a data pointer, which is what make_cleanup
expects. */
struct quit_handler_cleanup_data
{
/* The previous quit handler. */
quit_handler_ftype *prev_handler;
};
/* Cleanup call that restores the previous quit handler. */
static void
restore_quit_handler (void *arg)
{
struct quit_handler_cleanup_data *data
= (struct quit_handler_cleanup_data *) arg;
quit_handler = data->prev_handler;
}
/* Destructor for the quit handler cleanup. */
static void
restore_quit_handler_dtor (void *arg)
{
xfree (arg);
}
/* See defs.h. */
struct cleanup *
make_cleanup_override_quit_handler (quit_handler_ftype *new_quit_handler)
{
struct cleanup *old_chain;
struct quit_handler_cleanup_data *data;
data = XNEW (struct quit_handler_cleanup_data);
data->prev_handler = quit_handler;
old_chain = make_cleanup_dtor (restore_quit_handler, data,
restore_quit_handler_dtor);
quit_handler = new_quit_handler;
return old_chain;
}
/* Handle a SIGINT. */
void
@ -921,9 +983,7 @@ async_request_quit (gdb_client_data arg)
back here, that means that an exception was thrown to unwind the
current command before we got back to the event loop. So there
is no reason to call quit again here. */
if (check_quit_flag ())
quit ();
QUIT;
}
#ifdef SIGQUIT

View File

@ -97,14 +97,10 @@ static char *remote_exec_file_var;
enum { REMOTE_ALIGN_WRITES = 16 };
/* Prototypes for local functions. */
static void async_cleanup_sigint_signal_handler (void *dummy);
static int getpkt_sane (char **buf, long *sizeof_buf, int forever);
static int getpkt_or_notif_sane (char **buf, long *sizeof_buf,
int forever, int *is_notif);
static void async_handle_remote_sigint (int);
static void async_handle_remote_sigint_twice (int);
static void remote_files_info (struct target_ops *ignore);
static void remote_prepare_to_store (struct target_ops *self,
@ -141,8 +137,6 @@ static void remote_async (struct target_ops *ops, int enable);
static void remote_thread_events (struct target_ops *ops, int enable);
static void sync_remote_interrupt_twice (int signo);
static void interrupt_query (void);
static void set_general_thread (struct ptid ptid);
@ -241,6 +235,8 @@ static int stop_reply_queue_length (void);
static void readahead_cache_invalidate (void);
static void remote_unpush_and_throw (void);
/* For "remote". */
static struct cmd_list_element *remote_cmdlist;
@ -363,6 +359,14 @@ struct remote_state
responded to that. */
int ctrlc_pending_p;
/* True if we saw a Ctrl-C while reading or writing from/to the
remote descriptor. At that point it is not safe to send a remote
interrupt packet, so we instead remember we saw the Ctrl-C and
process it once we're done with sending/receiving the current
packet, which should be shortly. If however that takes too long,
and the user presses Ctrl-C again, we offer to disconnect. */
int got_ctrlc_during_io;
/* Descriptor for I/O to remote machine. Initialize it to NULL so that
remote_open knows that we don't have a file open when the program
starts. */
@ -1689,10 +1693,6 @@ remote_remove_exec_catchpoint (struct target_ops *ops, int pid)
return 0;
}
/* Tokens for use by the asynchronous signal handlers for SIGINT. */
static struct async_signal_handler *async_sigint_remote_twice_token;
static struct async_signal_handler *async_sigint_remote_token;
/* Asynchronous signal handle registered as event loop source for
when we have pending events ready to be passed to the core. */
@ -3497,8 +3497,7 @@ remote_close (struct target_ops *self)
if (rs->remote_desc == NULL)
return; /* already closed */
/* Make sure we leave stdin registered in the event loop, and we
don't leave the async SIGINT signal handler installed. */
/* Make sure we leave stdin registered in the event loop. */
remote_terminal_ours (self);
serial_close (rs->remote_desc);
@ -3994,6 +3993,8 @@ process_initial_stop_replies (int from_tty)
set_last_target_status (inferior_ptid, thread->suspend.waitstatus);
}
/* Start the remote connection and sync state. */
static void
remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
{
@ -4001,18 +4002,21 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
struct packet_config *noack_config;
char *wait_status = NULL;
immediate_quit++; /* Allow user to interrupt it. */
/* Signal other parts that we're going through the initial setup,
and so things may not be stable yet. E.g., we don't try to
install tracepoints until we've relocated symbols. Also, a
Ctrl-C before we're connected and synced up can't interrupt the
target. Instead, it offers to drop the (potentially wedged)
connection. */
rs->starting_up = 1;
QUIT;
if (interrupt_on_connect)
send_interrupt_sequence ();
/* Ack any packet which the remote side has already sent. */
serial_write (rs->remote_desc, "+", 1);
/* Signal other parts that we're going through the initial setup,
and so things may not be stable yet. */
rs->starting_up = 1;
remote_serial_write ("+", 1);
/* The first packet we send to the target is the optional "supported
packets" request. If the target can answer this, it will tell us
@ -4197,7 +4201,6 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
strcpy (rs->buf, wait_status);
rs->cached_wait_status = 1;
immediate_quit--;
start_remote (from_tty); /* Initialize gdb process mechanisms. */
}
else
@ -4833,6 +4836,58 @@ remote_query_supported (void)
}
}
/* Serial QUIT handler for the remote serial descriptor.
Defers handling a Ctrl-C until we're done with the current
command/response packet sequence, unless:
- We're setting up the connection. Don't send a remote interrupt
request, as we're not fully synced yet. Quit immediately
instead.
- The target has been resumed in the foreground
(target_terminal_is_ours is false) with a synchronous resume
packet, and we're blocked waiting for the stop reply, thus a
Ctrl-C should be immediately sent to the target.
- We get a second Ctrl-C while still within the same serial read or
write. In that case the serial is seemingly wedged --- offer to
quit/disconnect.
- We see a second Ctrl-C without target response, after having
previously interrupted the target. In that case the target/stub
is probably wedged --- offer to quit/disconnect.
*/
static void
remote_serial_quit_handler (void)
{
struct remote_state *rs = get_remote_state ();
if (check_quit_flag ())
{
/* If we're starting up, we're not fully synced yet. Quit
immediately. */
if (rs->starting_up)
quit ();
else if (rs->got_ctrlc_during_io)
{
if (query (_("The target is not responding to GDB commands.\n"
"Stop debugging it? ")))
remote_unpush_and_throw ();
}
/* If ^C has already been sent once, offer to disconnect. */
else if (!target_terminal_is_ours () && rs->ctrlc_pending_p)
interrupt_query ();
/* All-stop protocol, and blocked waiting for stop reply. Send
an interrupt request. */
else if (!target_terminal_is_ours () && rs->waiting_for_stop_reply)
target_interrupt (inferior_ptid);
else
rs->got_ctrlc_during_io = 1;
}
}
/* Remove any of the remote.c targets from target stack. Upper targets depend
on it so remove them first. */
@ -4842,6 +4897,13 @@ remote_unpush_target (void)
pop_all_targets_at_and_above (process_stratum);
}
static void
remote_unpush_and_throw (void)
{
remote_unpush_target ();
throw_error (TARGET_CLOSE_ERROR, _("Disconnected from target."));
}
static void
remote_open_1 (const char *name, int from_tty,
struct target_ops *target, int extended_p)
@ -4931,6 +4993,7 @@ remote_open_1 (const char *name, int from_tty,
rs->extended = extended_p;
rs->waiting_for_stop_reply = 0;
rs->ctrlc_pending_p = 0;
rs->got_ctrlc_during_io = 0;
rs->general_thread = not_sent_ptid;
rs->continue_thread = not_sent_ptid;
@ -4942,11 +5005,11 @@ remote_open_1 (const char *name, int from_tty,
readahead_cache_invalidate ();
/* Start out by owning the terminal. */
remote_async_terminal_ours_p = 1;
if (target_async_permitted)
{
/* With this target we start out by owning the terminal. */
remote_async_terminal_ours_p = 1;
/* FIXME: cagney/1999-09-23: During the initial connection it is
assumed that the target is already ready and able to respond to
requests. Unfortunately remote_start_remote() eventually calls
@ -5637,108 +5700,6 @@ remote_resume (struct target_ops *ops,
}
/* Set up the signal handler for SIGINT, while the target is
executing, ovewriting the 'regular' SIGINT signal handler. */
static void
async_initialize_sigint_signal_handler (void)
{
signal (SIGINT, async_handle_remote_sigint);
}
/* Signal handler for SIGINT, while the target is executing. */
static void
async_handle_remote_sigint (int sig)
{
signal (sig, async_handle_remote_sigint_twice);
/* Note we need to go through gdb_call_async_signal_handler in order
to wake up the event loop on Windows. */
gdb_call_async_signal_handler (async_sigint_remote_token, 0);
}
/* Signal handler for SIGINT, installed after SIGINT has already been
sent once. It will take effect the second time that the user sends
a ^C. */
static void
async_handle_remote_sigint_twice (int sig)
{
signal (sig, async_handle_remote_sigint);
/* See note in async_handle_remote_sigint. */
gdb_call_async_signal_handler (async_sigint_remote_twice_token, 0);
}
/* Implementation of to_check_pending_interrupt. */
static void
remote_check_pending_interrupt (struct target_ops *self)
{
struct async_signal_handler *token = async_sigint_remote_twice_token;
if (async_signal_handler_is_marked (token))
{
clear_async_signal_handler (token);
call_async_signal_handler (token);
}
}
/* Perform the real interruption of the target execution, in response
to a ^C. */
static void
async_remote_interrupt (gdb_client_data arg)
{
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "async_remote_interrupt called\n");
target_interrupt (inferior_ptid);
}
/* Perform interrupt, if the first attempt did not succeed. Just give
up on the target alltogether. */
static void
async_remote_interrupt_twice (gdb_client_data arg)
{
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "async_remote_interrupt_twice called\n");
interrupt_query ();
}
/* Reinstall the usual SIGINT handlers, after the target has
stopped. */
static void
async_cleanup_sigint_signal_handler (void *dummy)
{
signal (SIGINT, handle_sigint);
}
/* Send ^C to target to halt it. Target will respond, and send us a
packet. */
static void (*ofunc) (int);
/* The command line interface's interrupt routine. This function is installed
as a signal handler for SIGINT. The first time a user requests an
interrupt, we call remote_interrupt to send a break or ^C. If there is no
response from the target (it didn't stop when the user requested it),
we ask the user if he'd like to detach from the target. */
static void
sync_remote_interrupt (int signo)
{
/* If this doesn't work, try more severe steps. */
signal (signo, sync_remote_interrupt_twice);
gdb_call_async_signal_handler (async_sigint_remote_token, 1);
}
/* The user typed ^C twice. */
static void
sync_remote_interrupt_twice (int signo)
{
signal (signo, ofunc);
gdb_call_async_signal_handler (async_sigint_remote_twice_token, 1);
signal (signo, sync_remote_interrupt);
}
/* Non-stop version of target_stop. Uses `vCont;t' to stop a remote
thread, all threads of a remote process, or all threads of all
processes. */
@ -5928,10 +5889,6 @@ interrupt_query (void)
static void
remote_terminal_inferior (struct target_ops *self)
{
if (!target_async_permitted)
/* Nothing to do. */
return;
/* FIXME: cagney/1999-09-27: Make calls to target_terminal_*()
idempotent. The event-loop GDB talking to an asynchronous target
with a synchronous command calls this function from both
@ -5942,7 +5899,6 @@ remote_terminal_inferior (struct target_ops *self)
return;
delete_file_handler (input_fd);
remote_async_terminal_ours_p = 0;
async_initialize_sigint_signal_handler ();
/* NOTE: At this point we could also register our selves as the
recipient of all input. Any characters typed could then be
passed on down to the target. */
@ -5951,14 +5907,9 @@ remote_terminal_inferior (struct target_ops *self)
static void
remote_terminal_ours (struct target_ops *self)
{
if (!target_async_permitted)
/* Nothing to do. */
return;
/* See FIXME in remote_terminal_inferior. */
if (remote_async_terminal_ours_p)
return;
async_cleanup_sigint_signal_handler (NULL);
add_file_handler (input_fd, stdin_event_handler, 0);
remote_async_terminal_ours_p = 1;
}
@ -6929,15 +6880,6 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
return minus_one_ptid;
}
if (!target_is_async_p ())
{
ofunc = signal (SIGINT, sync_remote_interrupt);
/* If the user hit C-c before this packet, or between packets,
pretend that it was hit right here. */
if (check_quit_flag ())
sync_remote_interrupt (SIGINT);
}
/* FIXME: cagney/1999-09-27: If we're in async mode we should
_never_ wait for ever -> test on target_is_async_p().
However, before we do that we need to ensure that the caller
@ -6945,9 +6887,6 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
ret = getpkt_or_notif_sane (&rs->buf, &rs->buf_size,
forever, &is_notif);
if (!target_is_async_p ())
signal (SIGINT, ofunc);
/* GDB gets a notification. Return to core as this event is
not interesting. */
if (ret != -1 && is_notif)
@ -8165,16 +8104,29 @@ unpush_and_perror (const char *string)
safe_strerror (saved_errno));
}
/* Read a single character from the remote end. */
/* Read a single character from the remote end. The current quit
handler is overridden to avoid quitting in the middle of packet
sequence, as that would break communication with the remote server.
See remote_serial_quit_handler for more detail. */
static int
readchar (int timeout)
{
int ch;
struct remote_state *rs = get_remote_state ();
struct cleanup *old_chain;
old_chain = make_cleanup_override_quit_handler (remote_serial_quit_handler);
rs->got_ctrlc_during_io = 0;
ch = serial_readchar (rs->remote_desc, timeout);
if (rs->got_ctrlc_during_io)
set_quit_flag ();
do_cleanups (old_chain);
if (ch >= 0)
return ch;
@ -8195,18 +8147,31 @@ readchar (int timeout)
}
/* Wrapper for serial_write that closes the target and throws if
writing fails. */
writing fails. The current quit handler is overridden to avoid
quitting in the middle of packet sequence, as that would break
communication with the remote server. See
remote_serial_quit_handler for more detail. */
static void
remote_serial_write (const char *str, int len)
{
struct remote_state *rs = get_remote_state ();
struct cleanup *old_chain;
old_chain = make_cleanup_override_quit_handler (remote_serial_quit_handler);
rs->got_ctrlc_during_io = 0;
if (serial_write (rs->remote_desc, str, len))
{
unpush_and_perror (_("Remote communication error. "
"Target disconnected."));
}
if (rs->got_ctrlc_during_io)
set_quit_flag ();
do_cleanups (old_chain);
}
/* Send the command in *BUF to the remote machine, and read the reply
@ -8731,7 +8696,6 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever,
if (forever) /* Watchdog went off? Kill the target. */
{
QUIT;
remote_unpush_target ();
throw_error (TARGET_CLOSE_ERROR,
_("Watchdog timeout has expired. "
@ -13072,7 +13036,6 @@ Specify the serial device it is connected to\n\
remote_ops.to_stop = remote_stop;
remote_ops.to_interrupt = remote_interrupt;
remote_ops.to_pass_ctrlc = remote_pass_ctrlc;
remote_ops.to_check_pending_interrupt = remote_check_pending_interrupt;
remote_ops.to_xfer_partial = remote_xfer_partial;
remote_ops.to_rcmd = remote_rcmd;
remote_ops.to_pid_to_exec_file = remote_pid_to_exec_file;
@ -13473,12 +13436,6 @@ _initialize_remote (void)
when it exits. */
observer_attach_inferior_exit (discard_pending_stop_replies);
/* Set up signal handlers. */
async_sigint_remote_token =
create_async_signal_handler (async_remote_interrupt, NULL);
async_sigint_remote_twice_token =
create_async_signal_handler (async_remote_interrupt_twice, NULL);
#if 0
init_remote_threadtests ();
#endif

View File

@ -213,6 +213,7 @@ ser_base_wait_for (struct serial *scb, int timeout)
int numfds;
struct timeval tv;
fd_set readfds, exceptfds;
int nfds;
/* NOTE: Some OS's can scramble the READFDS when the select()
call fails (ex the kernel with Red Hat 5.2). Initialize all
@ -226,10 +227,13 @@ ser_base_wait_for (struct serial *scb, int timeout)
FD_SET (scb->fd, &readfds);
FD_SET (scb->fd, &exceptfds);
QUIT;
nfds = scb->fd + 1;
if (timeout >= 0)
numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
numfds = interruptible_select (nfds, &readfds, 0, &exceptfds, &tv);
else
numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
numfds = interruptible_select (nfds, &readfds, 0, &exceptfds, 0);
if (numfds <= 0)
{
@ -455,6 +459,8 @@ ser_base_write (struct serial *scb, const void *buf, size_t count)
while (count > 0)
{
QUIT;
cc = scb->ops->write_prim (scb, str, count);
if (cc < 0)

View File

@ -616,6 +616,8 @@ dos_readchar (struct serial *scb, int timeout)
then = rawclock () + (timeout * RAWHZ);
while ((c = dos_getc (port)) < 0)
{
QUIT;
if (timeout >= 0 && (rawclock () - then) >= 0)
return SERIAL_TIMEOUT;
}
@ -794,6 +796,8 @@ dos_write (struct serial *scb, const void *buf, size_t count)
while (count > 0)
{
QUIT;
/* Send the data, fifosize bytes at a time. */
cnt = fifosize > count ? count : fifosize;
port->txbusy = 1;

View File

@ -449,10 +449,7 @@ hardwire_raw (struct serial *scb)
}
/* Wait for input on scb, with timeout seconds. Returns 0 on success,
otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
For termio{s}, we actually just setup VTIME if necessary, and let the
timeout occur in the read() in hardwire_read(). */
otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */
/* FIXME: cagney/1999-09-16: Don't replace this with the equivalent
ser_base*() until the old TERMIOS/SGTTY/... timer code has been
@ -466,7 +463,6 @@ hardwire_raw (struct serial *scb)
static int
wait_for (struct serial *scb, int timeout)
{
#ifdef HAVE_SGTTY
while (1)
{
struct timeval tv;
@ -483,92 +479,22 @@ wait_for (struct serial *scb, int timeout)
FD_ZERO (&readfds);
FD_SET (scb->fd, &readfds);
if (timeout >= 0)
numfds = gdb_select (scb->fd + 1, &readfds, 0, 0, &tv);
else
numfds = gdb_select (scb->fd + 1, &readfds, 0, 0, 0);
QUIT;
if (numfds <= 0)
if (numfds == 0)
return SERIAL_TIMEOUT;
else if (errno == EINTR)
continue;
else
return SERIAL_ERROR; /* Got an error from select or poll. */
if (timeout >= 0)
numfds = interruptible_select (scb->fd + 1, &readfds, 0, 0, &tv);
else
numfds = interruptible_select (scb->fd + 1, &readfds, 0, 0, 0);
if (numfds == -1 && errno == EINTR)
continue;
else if (numfds == -1)
return SERIAL_ERROR;
else if (numfds == 0)
return SERIAL_TIMEOUT;
return 0;
}
#endif /* HAVE_SGTTY */
#if defined HAVE_TERMIO || defined HAVE_TERMIOS
if (timeout == scb->current_timeout)
return 0;
scb->current_timeout = timeout;
{
struct hardwire_ttystate state;
if (get_tty_state (scb, &state))
fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n",
safe_strerror (errno));
#ifdef HAVE_TERMIOS
if (timeout < 0)
{
/* No timeout. */
state.termios.c_cc[VTIME] = 0;
state.termios.c_cc[VMIN] = 1;
}
else
{
state.termios.c_cc[VMIN] = 0;
state.termios.c_cc[VTIME] = timeout * 10;
if (state.termios.c_cc[VTIME] != timeout * 10)
{
/* If c_cc is an 8-bit signed character, we can't go
bigger than this. If it is always unsigned, we could use
25. */
scb->current_timeout = 12;
state.termios.c_cc[VTIME] = scb->current_timeout * 10;
scb->timeout_remaining = timeout - scb->current_timeout;
}
}
#endif
#ifdef HAVE_TERMIO
if (timeout < 0)
{
/* No timeout. */
state.termio.c_cc[VTIME] = 0;
state.termio.c_cc[VMIN] = 1;
}
else
{
state.termio.c_cc[VMIN] = 0;
state.termio.c_cc[VTIME] = timeout * 10;
if (state.termio.c_cc[VTIME] != timeout * 10)
{
/* If c_cc is an 8-bit signed character, we can't go
bigger than this. If it is always unsigned, we could use
25. */
scb->current_timeout = 12;
state.termio.c_cc[VTIME] = scb->current_timeout * 10;
scb->timeout_remaining = timeout - scb->current_timeout;
}
}
#endif
if (set_tty_state (scb, &state))
fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n",
safe_strerror (errno));
return 0;
}
#endif /* HAVE_TERMIO || HAVE_TERMIOS */
}
/* Read a character with user-specified timeout. TIMEOUT is number of

View File

@ -1086,11 +1086,13 @@ quit (void)
void
maybe_quit (void)
{
if (check_quit_flag () || sync_quit_force_run)
if (sync_quit_force_run)
quit ();
quit_handler ();
if (deprecated_interactive_hook)
deprecated_interactive_hook ();
target_check_pending_interrupt ();
}
@ -1318,6 +1320,7 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args)
/* We'll need to handle input. */
target_terminal_ours ();
make_cleanup_override_quit_handler (default_quit_handler);
while (1)
{
@ -1892,6 +1895,7 @@ prompt_for_continue (void)
/* We'll need to handle input. */
make_cleanup_restore_target_terminal ();
target_terminal_ours ();
make_cleanup_override_quit_handler (default_quit_handler);
/* Call gdb_readline_wrapper, not readline, in order to keep an
event loop running. */