gdb: add interp::on_signal_received method
authorSimon Marchi <simon.marchi@efficios.com>
Wed, 1 Mar 2023 21:48:36 +0000 (16:48 -0500)
committerSimon Marchi <simon.marchi@efficios.com>
Tue, 30 May 2023 19:07:26 +0000 (15:07 -0400)
Instead of having the interpreter code registering observers for the
signal_received observable, add a "signal_received" virtual method to
struct interp.  Add a interps_notify_signal_received function that loops
over all UIs and calls the signal_received method on the interpreter.
Finally, add a notify_signal_received function that calls
interps_notify_signal_received and then notifies the observers.  Replace
all existing notifications to the signal_received observers with calls
to notify_signal_received.

Before this patch, the CLI and MI code both register a signal_received
observer.  These observer go over all UIs, and, for those that have a
interpreter of the right kind, print the stop notifiation.

After this patch, we have just one "loop over all UIs", inside
interps_notify_signal_received.  Since the interp::on_signal_received
method gets called once for each interpreter, the implementations only
need to deal with the current interpreter (the "this" pointer).

The motivation for this patch comes from a future patch, that makes the
amdgpu code register an observer to print a warning after the CLI's
signal stop message.  Since the amdgpu and the CLI code both use
observers, the order of the two messages is not stable, unless we define
the priority using the observer dependency system.  However, the
approach of using virtual methods on the interpreters seems like a good
change anyway, I think it's more straightforward and simple to
understand than the current solution that uses observers.  We are sure
that the amdgpu message gets printed after the CLI message, since
observers are notified after interpreters.

Keep the signal_received, even if nothing uses if, because we will be
using it in the upcoming amdgpu patch implementing the warning described
above.

Change-Id: I4d8614bb8f6e0717f4bfc2a59abded3702f23ac4

gdb/cli/cli-interp.c
gdb/cli/cli-interp.h
gdb/infrun.c
gdb/infrun.h
gdb/interps.c
gdb/interps.h
gdb/mi/mi-interp.c
gdb/mi/mi-interp.h
gdb/remote.c

index 84fe34a101485ad9f5f076de30c7586ee395d7aa..51c78d96ee20a125ab42a7897f66fe3353879a08 100644 (file)
@@ -137,19 +137,10 @@ cli_base_on_normal_stop (struct bpstat *bs, int print_frame)
     }
 }
 
-/* Observer for the signal_received notification.  */
-
-static void
-cli_base_on_signal_received (enum gdb_signal siggnal)
+void
+cli_interp_base::on_signal_received (enum gdb_signal siggnal)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ());
-      if (cli == nullptr)
-       continue;
-
-      print_signal_received_reason (cli->interp_ui_out (), siggnal);
-    }
+  print_signal_received_reason (this->interp_ui_out (), siggnal);
 }
 
 /* Observer for the signalled notification.  */
@@ -408,8 +399,6 @@ _initialize_cli_interp ()
   /* Note these all work for both the CLI and TUI interpreters.  */
   gdb::observers::normal_stop.attach (cli_base_on_normal_stop,
                                      "cli-interp-base");
-  gdb::observers::signal_received.attach (cli_base_on_signal_received,
-                                         "cli-interp-base");
   gdb::observers::signal_exited.attach (cli_base_on_signal_exited,
                                        "cli-interp-base");
   gdb::observers::exited.attach (cli_base_on_exited, "cli-interp-base");
index 5ed998f58bd5301d8108c4162f3aeef818792da3..f7bee4530b425548a127d3899e4aed447d3b3028 100644 (file)
@@ -33,6 +33,8 @@ public:
   void pre_command_loop () override;
   bool supports_command_editing () override;
 
+  void on_signal_received (gdb_signal sig) override;
+
 private:
   struct saved_output_files
   {
index a9e2a2423b175af0717992964b0b6bcf4811e354..6a2973eacc475263af7fbd8c2930e2ce57010985 100644 (file)
@@ -76,6 +76,7 @@
 #include "gdbsupport/buildargv.h"
 #include "extension.h"
 #include "disasm.h"
+#include "interps.h"
 
 /* Prototypes for local functions */
 
@@ -6264,6 +6265,15 @@ finish_step_over (struct execution_control_state *ecs)
   return 0;
 }
 
+/* See infrun.h.  */
+
+void
+notify_signal_received (gdb_signal sig)
+{
+  interps_notify_signal_received (sig);
+  gdb::observers::signal_received.notify (sig);
+}
+
 /* Come here when the program has stopped with a signal.  */
 
 static void
@@ -6687,7 +6697,7 @@ handle_signal_stop (struct execution_control_state *ecs)
        {
          /* The signal table tells us to print about this signal.  */
          target_terminal::ours_for_output ();
-         gdb::observers::signal_received.notify (ecs->event_thread->stop_signal ());
+         notify_signal_received (ecs->event_thread->stop_signal ());
          target_terminal::inferior ();
        }
 
@@ -8829,7 +8839,7 @@ normal_stop ()
   update_thread_list ();
 
   if (last.kind () == TARGET_WAITKIND_STOPPED && stopped_by_random_signal)
-    gdb::observers::signal_received.notify (inferior_thread ()->stop_signal ());
+    notify_signal_received (inferior_thread ()->stop_signal ());
 
   /* As with the notification of thread events, we want to delay
      notifying the user that we've switched thread context until
index 9513bc570e467eee1441729793ebeedb80a952bf..f7b60a4d9fb70969f1021eca3b52d6a2656ef926 100644 (file)
@@ -210,6 +210,10 @@ extern void set_step_info (thread_info *tp,
                           frame_info_ptr frame,
                           struct symtab_and_line sal);
 
+/* Notify interpreters and observers that the current inferior has stopped with
+   signal SIG.  */
+extern void notify_signal_received (gdb_signal sig);
+
 /* Several print_*_reason helper functions to print why the inferior
    has stopped to the passed in UIOUT.  */
 
index e3f6ee6851238ec7b460250dacde7b1befbb1b5b..5d061ad52aff536500b76c271a8c495fb0710436 100644 (file)
@@ -383,6 +383,29 @@ current_interpreter (void)
   return current_ui->current_interpreter;
 }
 
+/* Helper interps_notify_* functions.  Call METHOD on the top-level interpreter
+   of all UIs.  */
+
+template <typename ...Args>
+void
+interps_notify (void (interp::*method) (Args...), Args... args)
+{
+  SWITCH_THRU_ALL_UIS ()
+    {
+      interp *tli = top_level_interpreter ();
+      if (tli != nullptr)
+       (tli->*method) (args...);
+    }
+}
+
+/* See interps.h.  */
+
+void
+interps_notify_signal_received (gdb_signal sig)
+{
+  interps_notify (&interp::on_signal_received, sig);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
index da78a5d89fae0cf36b2c2537c56e0c352b3be933..4762c4c93ff1823d016b39a83131f98624792dd9 100644 (file)
@@ -82,6 +82,10 @@ public:
   const char *name () const
   { return m_name; }
 
+  /* Notify the interpreter that the current inferior has stopped with signal
+     SIG.  */
+  virtual void on_signal_received (gdb_signal sig) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -170,6 +174,10 @@ extern void interpreter_completer (struct cmd_list_element *ignore,
                                   const char *text,
                                   const char *word);
 
+/* Notify all interpreters that the current inferior has stopped with signal
+   SIG.  */
+extern void interps_notify_signal_received (gdb_signal sig);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE         "console"
 #define INTERP_MI2             "mi2"
index d8b49ae644aba3e37c541db7feae5babca311cb8..b77494e42982763b9e479e7d00ff454c51bf5556 100644 (file)
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_on_signal_received (enum gdb_signal siggnal);
 static void mi_on_signal_exited (enum gdb_signal siggnal);
 static void mi_on_exited (int exitstatus);
 static void mi_on_normal_stop (struct bpstat *bs, int print_frame);
@@ -525,21 +524,11 @@ find_mi_interp (void)
    inferior has stopped to both the MI event channel and to the MI
    console.  If the MI interpreter is not active, print nothing.  */
 
-/* Observer for the signal_received notification.  */
-
-static void
-mi_on_signal_received (enum gdb_signal siggnal)
+void
+mi_interp::on_signal_received (enum gdb_signal siggnal)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = find_mi_interp ();
-
-      if (mi == NULL)
-       continue;
-
-      print_signal_received_reason (mi->mi_uiout, siggnal);
-      print_signal_received_reason (mi->cli_uiout, siggnal);
-    }
+  print_signal_received_reason (this->mi_uiout, siggnal);
+  print_signal_received_reason (this->cli_uiout, siggnal);
 }
 
 /* Observer for the signal_exited notification.  */
@@ -1304,7 +1293,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::signal_received.attach (mi_on_signal_received, "mi-interp");
   gdb::observers::signal_exited.attach (mi_on_signal_exited, "mi-interp");
   gdb::observers::exited.attach (mi_on_exited, "mi-interp");
   gdb::observers::no_history.attach (mi_on_no_history, "mi-interp");
index eb81cbe6cada1c9b8834409cd069547820087ac2..a8fd7b6bd9698c7fd13b0ecf7a74a6a67fdc16bb 100644 (file)
@@ -42,6 +42,8 @@ public:
                    bool debug_redirect) override;
   void pre_command_loop () override;
 
+  void on_signal_received (gdb_signal sig) override;
+
   /* MI's output channels */
   mi_console_file *out;
   mi_console_file *err;
index f7d5758cfdc582b447a3a624d456c572019020a9..0d82d0f88f1a8b7920b7d9e0864a7da44fb6e9ae 100644 (file)
@@ -4720,7 +4720,7 @@ remote_target::print_one_stopped_thread (thread_info *thread)
       enum gdb_signal sig = ws.sig ();
 
       if (signal_print_state (sig))
-       gdb::observers::signal_received.notify (sig);
+       notify_signal_received (sig);
     }
   gdb::observers::normal_stop.notify (NULL, 1);
 }