Pass Ctrl-C to the target in target_terminal_inferior

If the user presses Ctrl-C immediately before target_terminal_inferior
is called and the target is resumed, instead of after, the Ctrl-C ends
up pending in the quit flag until the target next stops.

remote.c has this bit to handle this:

      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);
	}

But that's only reachable if async is off, while async is on by
default nowadays.  It's also obviously not reacheable on native
targets.

This patch generalizes that to all targets.

We can't remove that remote.c bit yet, until we get rid of the sync
SIGINT handler though.  That'll be done later in the series.

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

	* remote.c (remote_pass_ctrlc): New function.
	(init_remote_ops): Install it.
	* target.c (target_terminal_inferior): Pass pending Ctrl-C to the
	target.
	(target_pass_ctrlc, default_target_pass_ctrlc): New functions.
	* target.h (struct target_ops) <to_pass_ctrlc>: New method.
	(target_pass_ctrlc, default_target_pass_ctrlc): New declarations.
	* target-delegates.c: Regenerate.
This commit is contained in:
Pedro Alves 2016-04-12 16:49:31 +01:00
parent e42de8c7f8
commit 93692b589d
5 changed files with 88 additions and 0 deletions

View File

@ -1,3 +1,14 @@
2016-04-12 Pedro Alves <palves@redhat.com>
* remote.c (remote_pass_ctrlc): New function.
(init_remote_ops): Install it.
* target.c (target_terminal_inferior): Pass pending Ctrl-C to the
target.
(target_pass_ctrlc, default_target_pass_ctrlc): New functions.
* target.h (struct target_ops) <to_pass_ctrlc>: New method.
(target_pass_ctrlc, default_target_pass_ctrlc): New declarations.
* target-delegates.c: Regenerate.
2016-04-12 Pedro Alves <palves@redhat.com>
* infcmd.c (interrupt_target_1): Call target_stop is in non-stop

View File

@ -5875,6 +5875,27 @@ remote_interrupt (struct target_ops *self, ptid_t ptid)
remote_interrupt_as ();
}
/* Implement the to_pass_ctrlc function for the remote targets. */
static void
remote_pass_ctrlc (struct target_ops *self)
{
struct remote_state *rs = get_remote_state ();
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "remote_pass_ctrlc called\n");
/* If we're starting up, we're not fully synced yet. Quit
immediately. */
if (rs->starting_up)
quit ();
/* If ^C has already been sent once, offer to disconnect. */
else if (rs->ctrlc_pending_p)
interrupt_query ();
else
target_interrupt (inferior_ptid);
}
/* Ask the user what to do when an interrupt is received. */
static void
@ -13056,6 +13077,7 @@ Specify the serial device it is connected to\n\
remote_ops.to_get_ada_task_ptid = remote_get_ada_task_ptid;
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;

View File

@ -1607,6 +1607,23 @@ debug_interrupt (struct target_ops *self, ptid_t arg1)
fputs_unfiltered (")\n", gdb_stdlog);
}
static void
delegate_pass_ctrlc (struct target_ops *self)
{
self = self->beneath;
self->to_pass_ctrlc (self);
}
static void
debug_pass_ctrlc (struct target_ops *self)
{
fprintf_unfiltered (gdb_stdlog, "-> %s->to_pass_ctrlc (...)\n", debug_target.to_shortname);
debug_target.to_pass_ctrlc (&debug_target);
fprintf_unfiltered (gdb_stdlog, "<- %s->to_pass_ctrlc (", debug_target.to_shortname);
target_debug_print_struct_target_ops_p (&debug_target);
fputs_unfiltered (")\n", gdb_stdlog);
}
static void
delegate_check_pending_interrupt (struct target_ops *self)
{
@ -4194,6 +4211,8 @@ install_delegators (struct target_ops *ops)
ops->to_stop = delegate_stop;
if (ops->to_interrupt == NULL)
ops->to_interrupt = delegate_interrupt;
if (ops->to_pass_ctrlc == NULL)
ops->to_pass_ctrlc = delegate_pass_ctrlc;
if (ops->to_check_pending_interrupt == NULL)
ops->to_check_pending_interrupt = delegate_check_pending_interrupt;
if (ops->to_rcmd == NULL)
@ -4442,6 +4461,7 @@ install_dummy_methods (struct target_ops *ops)
ops->to_thread_name = tdefault_thread_name;
ops->to_stop = tdefault_stop;
ops->to_interrupt = tdefault_interrupt;
ops->to_pass_ctrlc = default_target_pass_ctrlc;
ops->to_check_pending_interrupt = tdefault_check_pending_interrupt;
ops->to_rcmd = default_rcmd;
ops->to_pid_to_exec_file = tdefault_pid_to_exec_file;
@ -4598,6 +4618,7 @@ init_debug_target (struct target_ops *ops)
ops->to_thread_name = debug_thread_name;
ops->to_stop = debug_stop;
ops->to_interrupt = debug_interrupt;
ops->to_pass_ctrlc = debug_pass_ctrlc;
ops->to_check_pending_interrupt = debug_check_pending_interrupt;
ops->to_rcmd = debug_rcmd;
ops->to_pid_to_exec_file = debug_pid_to_exec_file;

View File

@ -491,6 +491,11 @@ target_terminal_inferior (void)
inferior's terminal modes. */
(*current_target.to_terminal_inferior) (&current_target);
terminal_state = terminal_is_inferior;
/* If the user hit C-c before, pretend that it was hit right
here. */
if (check_quit_flag ())
target_pass_ctrlc ();
}
/* See target.h. */
@ -3359,6 +3364,22 @@ target_interrupt (ptid_t ptid)
/* See target.h. */
void
target_pass_ctrlc (void)
{
(*current_target.to_pass_ctrlc) (&current_target);
}
/* See target.h. */
void
default_target_pass_ctrlc (struct target_ops *ops)
{
target_interrupt (inferior_ptid);
}
/* See target.h. */
void
target_check_pending_interrupt (void)
{

View File

@ -645,6 +645,8 @@ struct target_ops
TARGET_DEFAULT_IGNORE ();
void (*to_interrupt) (struct target_ops *, ptid_t)
TARGET_DEFAULT_IGNORE ();
void (*to_pass_ctrlc) (struct target_ops *)
TARGET_DEFAULT_FUNC (default_target_pass_ctrlc);
void (*to_check_pending_interrupt) (struct target_ops *)
TARGET_DEFAULT_IGNORE ();
void (*to_rcmd) (struct target_ops *,
@ -1716,6 +1718,17 @@ extern void target_stop (ptid_t ptid);
extern void target_interrupt (ptid_t ptid);
/* Pass a ^C, as determined to have been pressed by checking the quit
flag, to the target. Normally calls target_interrupt, but remote
targets may take the opportunity to detect the remote side is not
responding and offer to disconnect. */
extern void target_pass_ctrlc (void);
/* The default target_ops::to_pass_ctrlc implementation. Simply calls
target_interrupt. */
extern void default_target_pass_ctrlc (struct target_ops *ops);
/* Some targets install their own SIGINT handler while the target is
running. This method is called from the QUIT macro to give such
targets a chance to process a Ctrl-C. The target may e.g., choose