Print MI prompt on interrupted command
authorTom Tromey <tromey@adacore.com>
Thu, 6 Jan 2022 15:42:49 +0000 (08:42 -0700)
committerTom Tromey <tromey@adacore.com>
Fri, 25 Feb 2022 14:30:30 +0000 (07:30 -0700)
Joel noticed that if the remote dies unexpectedly during a command --
you can simulate this by using "continue" and then killing gdbserver
-- then the CLI will print a new prompt, but MI will not.  Later, we
found out that this was also filed in bugzilla as PR mi/23820.

The output looks something like this:

    | (gdb)
    | cont
    | &"cont\n"
    | ~"Continuing.\n"
    | ^running
    | *running,thread-id="all"
    | (gdb)
    | [... some output from GDB during program startup...]
    | =thread-exited,id="1",group-id="i1"
    | =thread-group-exited,id="i1"
    | &"Remote connection closed\n"

Now, what about that "(gdb)" in the middle?

That prompt comes from this questionable code in
mi-interp.c:mi_on_resume_1:

      /* This is what gdb used to do historically -- printing prompt
 even if it cannot actually accept any input.  This will be
 surely removed for MI3, and may be removed even earlier.  */
      if (current_ui->prompt_state == PROMPT_BLOCKED)
fputs_unfiltered ("(gdb) \n", mi->raw_stdout);

... which seems like something to remove.  But maybe the intent here
is that this prompt is sufficient, and MI clients must be ready to
handle output coming after a prompt.  On the other hand, if this code
*is* removed, then nothing would print a prompt in this scenario.

Anyway, the CLI and the TUI handle emitting the prompt here by hooking
into gdb::observers::command_error, but MI doesn't install an observer
here.

This patch adds the missing observer and arranges to show the MI
prompt.  Regression tested on x86-64 Fedora 34.

It seems like this area could be improved a bit, by having
start_event_loop call the prompt-displaying code directly, rather than
indirecting through an observer.  However, I haven't done this.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23820

gdb/mi/mi-interp.c

index f02a7cf3f106e9c1d6fa86810e504c6c49c73677..2c47024d5e6ad31d24ab7939b285954342074658 100644 (file)
@@ -112,6 +112,16 @@ as_mi_interp (struct interp *interp)
   return dynamic_cast<mi_interp *> (interp);
 }
 
+/* Observer for the command_error notification.  */
+
+static void
+mi_on_command_error ()
+{
+  mi_interp *mi = as_mi_interp (top_level_interpreter ());
+  if (mi != nullptr)
+    display_mi_prompt (mi);
+}
+
 void
 mi_interp::init (bool top_level)
 {
@@ -1369,6 +1379,7 @@ _initialize_mi_interp ()
                                              "mi-interp");
   gdb::observers::command_param_changed.attach (mi_command_param_changed,
                                                "mi-interp");
+  gdb::observers::command_error.attach (mi_on_command_error, "mi-interp");
   gdb::observers::memory_changed.attach (mi_memory_changed, "mi-interp");
   gdb::observers::sync_execution_done.attach (mi_on_sync_execution_done,
                                              "mi-interp");