[binutils-gdb] Print MI prompt on interrupted command

Tom Tromey tromey@sourceware.org
Fri Feb 25 14:32:33 GMT 2022


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e8b4efc3cf3d5d2c475b3e5c31439aa5bcd277ae

commit e8b4efc3cf3d5d2c475b3e5c31439aa5bcd277ae
Author: Tom Tromey <tromey@adacore.com>
Date:   Thu Jan 6 08:42:49 2022 -0700

    Print MI prompt on interrupted command
    
    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

Diff:
---
 gdb/mi/mi-interp.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index f02a7cf3f10..2c47024d5e6 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -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");


More information about the Gdb-cvs mailing list