public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] gdb: replace inferior::waiting_for_vfork_done with inferior::thread_waiting_for_vfork_done
@ 2022-04-05  2:12 Simon Marchi
  0 siblings, 0 replies; only message in thread
From: Simon Marchi @ 2022-04-05  2:12 UTC (permalink / raw)
  To: gdb-cvs

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

commit 6f5d514f9134452ecfe0694b9025291f5abf1080
Author: Simon Marchi <simon.marchi@polymtl.ca>
Date:   Tue Jan 11 21:40:34 2022 -0500

    gdb: replace inferior::waiting_for_vfork_done with inferior::thread_waiting_for_vfork_done
    
    The inferior::waiting_for_vfork_done flag indicates that some thread in
    that inferior is waiting for a vfork-done event.  Subsequent patches
    will need to know which thread precisely is waiting for that event.
    
    Replace the boolean flag (waiting_for_vfork_done) with a thread_info
    pointer (thread_waiting_for_vfork_done).
    
    I think there is a latent buglet in that waiting_for_vfork_done is
    currently not reset on inferior exec or exit.  I could imagine that if a
    thread in the parent process calls exec or exit while another thread of
    the parent process is waiting for its vfork child to exec or exit, we
    could end up with inferior::waiting_for_vfork_done without a thread
    actually waiting for a vfork-done event anymore.  And since that flag is
    checked in resume_1, things could misbehave there.
    
    Since the new field points to a thread_info object, and those are
    destroyed on exec or exit, it could be worse now since we could try to
    access freed memory, if thread_waiting_for_vfork_done were to point to a
    stale thread_info.  To avoid this, clear the field in
    infrun_inferior_exit and infrun_inferior_execd.
    
    Change-Id: I31b847278613a49ba03fc4915f74d9ceb228fdce

Diff:
---
 gdb/inferior.h |  8 ++++----
 gdb/infrun.c   | 14 +++++++++-----
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/gdb/inferior.h b/gdb/inferior.h
index caabc2ee8d8..f6e26a32feb 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -537,10 +537,10 @@ public:
      exits or execs.  */
   bool pending_detach = false;
 
-  /* True if this inferior is a vfork parent waiting for a vfork child
-     not under our control to be done with the shared memory region,
-     either by exiting or execing.  */
-  bool waiting_for_vfork_done = false;
+  /* If non-nullptr, points to a thread that called vfork and is now waiting
+     for a vfork child not under our control to be done with the shared memory
+     region, either by exiting or execing.  */
+  thread_info *thread_waiting_for_vfork_done = nullptr;
 
   /* True if we're in the process of detaching from this inferior.  */
   bool detaching = false;
diff --git a/gdb/infrun.c b/gdb/infrun.c
index ca6666cea1f..4b21b5ecda1 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -508,7 +508,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 	     insert breakpoints, so that we can debug it.  A
 	     subsequent child exec or exit is enough to know when does
 	     the child stops using the parent's address space.  */
-	  parent_inf->waiting_for_vfork_done = detach_fork;
+	  parent_inf->thread_waiting_for_vfork_done
+	    = detach_fork ? inferior_thread () : nullptr;
 	  parent_inf->pspace->breakpoints_not_allowed = detach_fork;
 	}
     }
@@ -640,7 +641,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
 	  child_inf->pending_detach = 0;
 	  parent_inf->vfork_child = child_inf;
 	  parent_inf->pending_detach = detach_fork;
-	  parent_inf->waiting_for_vfork_done = 0;
+	  parent_inf->thread_waiting_for_vfork_done = nullptr;
 	}
       else if (detach_fork)
 	{
@@ -1484,6 +1485,7 @@ static void
 infrun_inferior_exit (struct inferior *inf)
 {
   inf->displaced_step_state.reset ();
+  inf->thread_waiting_for_vfork_done = nullptr;
 }
 
 static void
@@ -1502,6 +1504,8 @@ infrun_inferior_execd (inferior *inf)
      one in progress at the time of the exec, it must have been the exec'ing
      thread.  */
   clear_step_over_info ();
+
+  inf->thread_waiting_for_vfork_done = nullptr;
 }
 
 /* If ON, and the architecture supports it, GDB will use displaced
@@ -2251,7 +2255,7 @@ resume_1 (enum gdb_signal sig)
   /* Depends on stepped_breakpoint.  */
   step = currently_stepping (tp);
 
-  if (current_inferior ()->waiting_for_vfork_done)
+  if (current_inferior ()->thread_waiting_for_vfork_done != nullptr)
     {
       /* Don't try to single-step a vfork parent that is waiting for
 	 the child to get out of the shared memory region (by exec'ing
@@ -2371,7 +2375,7 @@ resume_1 (enum gdb_signal sig)
       && use_displaced_stepping (tp)
       && !step_over_info_valid_p ()
       && sig == GDB_SIGNAL_0
-      && !current_inferior ()->waiting_for_vfork_done)
+      && current_inferior ()->thread_waiting_for_vfork_done == nullptr)
     {
       displaced_step_prepare_status prepare_status
 	= displaced_step_prepare (tp);
@@ -5607,7 +5611,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       context_switch (ecs);
 
-      current_inferior ()->waiting_for_vfork_done = 0;
+      current_inferior ()->thread_waiting_for_vfork_done = nullptr;
       current_inferior ()->pspace->breakpoints_not_allowed = 0;
 
       if (handle_stop_requested (ecs))


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-04-05  2:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-05  2:12 [binutils-gdb] gdb: replace inferior::waiting_for_vfork_done with inferior::thread_waiting_for_vfork_done Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).