+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
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
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;
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)
{
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)
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;
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;
inferior's terminal modes. */
(*current_target.to_terminal_inferior) (¤t_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. */
/* See target.h. */
+void
+target_pass_ctrlc (void)
+{
+ (*current_target.to_pass_ctrlc) (¤t_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)
{
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 *,
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