[RFC,2/7] gdb: handle early replay diversion exits

Message ID vz&zz76a8direh7&n-98/xw&um2he5cjn3-yl.7rbldhv.o/_k2e@mail.bob131.so
State New
Headers show
Series
  • gdb: replay diversion support
Related show

Commit Message

Luis Machado via Gdb-patches June 1, 2021, 7:10 p.m.
Diversions of deterministic replay targets may exit early (if, for
example, a diversion was started for an inferior call to
`exit()'). This commit allows targets to notify of an early diversion
exit from `target_wait()' and has the GDB core handle it as an exit
without mourning the inferior.

gdb/ChangeLog:

2021-06-01  George Barrett  <bob@bob131.so>

	* infrun.c (handle_inferior_event): Don't check for a thread
	for TARGET_WAITKIND_REPLAY_DIVERSION_ENDED since it's
	inferior-wide.
	Handle TARGET_WAITKIND_REPLAY_DIVERSION_ENDED like an exit or
	a fatal signal, but don't mourn the inferior.
	(normal_stop): Don't assume the current thread will still be
	alive after a replay diversion has exited.
	Don't print "[Switching to x]" message for replay diversion
	exits.  Instead, print "[Replay diversion ended]".
	* target/waitstatus.c (target_waitstatus_to_string): Handle
	TARGET_WAITKIND_REPLAY_DIVERSION_ENDED.
	* target/waitstatus.h
	(target_waitkind::TARGET_WAITKIND_REPLAY_DIVERSION_ENDED): Add
	definition.
---
 gdb/infrun.c            | 25 ++++++++++++++++++++-----
 gdb/target/waitstatus.c |  2 ++
 gdb/target/waitstatus.h |  4 ++++
 3 files changed, 26 insertions(+), 5 deletions(-)

-- 
2.31.1

Patch

diff --git a/gdb/infrun.c b/gdb/infrun.c
index e9624d2a9b6..166f1e513c4 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5269,7 +5269,8 @@  handle_inferior_event (struct execution_control_state *ecs)
     }
 
   if (ecs->ws.kind != TARGET_WAITKIND_EXITED
-      && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED)
+      && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+      && ecs->ws.kind != TARGET_WAITKIND_REPLAY_DIVERSION_ENDED)
     {
       ecs->event_thread = find_thread_ptid (ecs->target, ecs->ptid);
       /* If it's a new thread, add it to the thread database.  */
@@ -5414,6 +5415,7 @@  handle_inferior_event (struct execution_control_state *ecs)
 
     case TARGET_WAITKIND_EXITED:
     case TARGET_WAITKIND_SIGNALLED:
+    case TARGET_WAITKIND_REPLAY_DIVERSION_ENDED:
       {
 	/* Depending on the system, ecs->ptid may point to a thread or
 	   to a process.  On some targets, target_mourn_inferior may
@@ -5451,7 +5453,7 @@  handle_inferior_event (struct execution_control_state *ecs)
 
 	  gdb::observers::exited.notify (ecs->ws.value.integer);
 	}
-      else
+      else if (ecs->ws.kind == TARGET_WAITKIND_SIGNALLED)
 	{
 	  struct gdbarch *gdbarch = current_inferior ()->gdbarch;
 
@@ -5480,7 +5482,9 @@  handle_inferior_event (struct execution_control_state *ecs)
 	}
 
       gdb_flush (gdb_stdout);
-      target_mourn_inferior (inferior_ptid);
+      if (ecs->ws.kind == TARGET_WAITKIND_EXITED
+	  || ecs->ws.kind == TARGET_WAITKIND_SIGNALLED)
+	target_mourn_inferior (inferior_ptid);
       stop_print_frame = false;
       stop_waiting (ecs);
       return;
@@ -8493,7 +8497,8 @@  normal_stop (void)
   if (!non_stop)
     finish_ptid = minus_one_ptid;
   else if (last.kind == TARGET_WAITKIND_SIGNALLED
-	   || last.kind == TARGET_WAITKIND_EXITED)
+	   || last.kind == TARGET_WAITKIND_EXITED
+	   || last.kind == TARGET_WAITKIND_REPLAY_DIVERSION_ENDED)
     {
       /* On some targets, we may still have live threads in the
 	 inferior when we get a process exit event.  E.g., for
@@ -8547,7 +8552,8 @@  normal_stop (void)
       && target_has_execution ()
       && last.kind != TARGET_WAITKIND_SIGNALLED
       && last.kind != TARGET_WAITKIND_EXITED
-      && last.kind != TARGET_WAITKIND_NO_RESUMED)
+      && last.kind != TARGET_WAITKIND_NO_RESUMED
+      && last.kind != TARGET_WAITKIND_REPLAY_DIVERSION_ENDED)
     {
       SWITCH_THRU_ALL_UIS ()
 	{
@@ -8569,6 +8575,15 @@  normal_stop (void)
 	  }
     }
 
+  if (last.kind == TARGET_WAITKIND_REPLAY_DIVERSION_ENDED)
+    {
+      SWITCH_THRU_ALL_UIS ()
+	{
+	  target_terminal::ours_for_output ();
+	  printf_filtered (_("[Replay diversion ended]\n"));
+	}
+    }
+
   /* Note: this depends on the update_thread_list call above.  */
   maybe_remove_breakpoints ();
 
diff --git a/gdb/target/waitstatus.c b/gdb/target/waitstatus.c
index c4fb061b293..3ea88c2a81a 100644
--- a/gdb/target/waitstatus.c
+++ b/gdb/target/waitstatus.c
@@ -67,6 +67,8 @@  target_waitstatus_to_string (const struct target_waitstatus *ws)
     case TARGET_WAITKIND_THREAD_EXITED:
       return string_printf ("%sthread exited, status = %d",
 			    kind_str, ws->value.integer);
+    case TARGET_WAITKIND_REPLAY_DIVERSION_ENDED:
+      return string_printf ("%sreplay diversion ended", kind_str);
     default:
       return string_printf ("%sunknown???", kind_str);
     }
diff --git a/gdb/target/waitstatus.h b/gdb/target/waitstatus.h
index 4123f42af5f..69c47040b25 100644
--- a/gdb/target/waitstatus.h
+++ b/gdb/target/waitstatus.h
@@ -99,6 +99,10 @@  enum target_waitkind
 
   /* The thread has exited.  The exit status is in value.integer.  */
   TARGET_WAITKIND_THREAD_EXITED,
+
+  /* An unexpected process exit occured during a diversion of
+     execution from a deterministic replay target.  */
+  TARGET_WAITKIND_REPLAY_DIVERSION_ENDED,
 };
 
 struct target_waitstatus