[PATCH 8/8] Fix PR gdb/14766 - vfork child exit with "set follow-fork-mode child" broken.

Pedro Alves palves@redhat.com
Thu Oct 25 17:42:00 GMT 2012

If "set detach-on-fork" is off (which it is by default), and we follow
the vfork child, we don't actually detach from the parent at vfork
time, but instead hold on to it until the child is done with the
shared memory region.  IOW, until the child execs or exits.  There's a
single function that handles all that work for both child execs and
exits, handle_vfork_child_exec_or_exit.  When that function goes about
detaching the parent, it tries to preserve the selected inferior (the
child), but while doing so, it is also trying to restore the selected
thread (as pointed at by inferior_ptid).  That makes sense for execs,
but not so for exits.  For exits, inferior_ptid, which has been
switched to the event ptid, does not point at a valid thread anymore.
Instead it just points at the process's pid.  The result is:

(gdb) r
Starting program:
[New process 4673]
I'm the child!
I'm the proud parent of child #4673!
Couldn't get registers: No such process.
Couldn't get registers: No such process.
Couldn't get registers: No such process.

The fix is not try to restore the thread, but just the inferior.

The bit in tcatch_vfork_then_child_follow_exit that kfails this PR is
just removed, as there's a specific test for this bug in the file.  It
was put there originally as this bug masked the gdb/14762 bug, and
thus the related gdb/14762 kfail in
tcatch_vfork_then_child_follow_exit was not reached.

2012-10-25  Pedro Alves  <palves@redhat.com>

	PR gdb/14766

	* infrun.c (handle_inferior_event)
	null_ptid before handling a vfork child exec or exit.  Switch to
	the event ptid afterwards.

2012-10-25  Pedro Alves  <palves@redhat.com>

	PR gdb/14766

	* gdb.base/foll-vfork.exp (vfork_child_follow_to_exit): Remove
	(tcatch_vfork_then_child_follow_exit): No longer expect "Couldn't
	get registers".
 gdb/testsuite/gdb.base/foll-vfork.exp |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0caa1ac..de9b137 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -663,7 +663,16 @@ handle_vfork_child_exec_or_exit (int exec)
 	  /* follow-fork child, detach-on-fork on.  */
-	  old_chain = make_cleanup_restore_current_thread ();
+	  if (!exec)
+	    {
+	      /* If we're handling a child exit, then inferior_ptid
+		 points at the inferior's pid, not to a thread.  */
+	      old_chain = save_inferior_ptid ();
+	      save_current_program_space ();
+	      save_current_inferior ();
+	    }
+	  else
+	    old_chain = save_current_space_and_thread ();
 	  /* We're letting loose of the parent.  */
 	  tp = any_live_thread_of_process (inf->vfork_parent->pid);
diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp
index ca04cdc..12f7ec7 100644
--- a/gdb/testsuite/gdb.base/foll-vfork.exp
+++ b/gdb/testsuite/gdb.base/foll-vfork.exp
@@ -162,7 +162,7 @@ proc vfork_child_follow_to_exit {} {
    set test "continue to child exit"
    gdb_test_multiple "continue" $test {
       -re "Couldn't get registers.*$gdb_prompt " {
-	  setup_kfail "gdb/14766" *-*-*
+	  # PR gdb/14766
 	  fail "$test"
       -re "Attaching after.* vfork to.*Detaching vfork parent .* after child exit.*$gdb_prompt " {
@@ -367,10 +367,6 @@ proc tcatch_vfork_then_child_follow_exit {} {
    set test "finish"
    gdb_test_multiple "finish" $test {
-      -re "Couldn't get registers.*$gdb_prompt " {
-	  setup_kfail "gdb/14766" *-*-*
-	  fail "$test "
-      }
       -re "Run till exit from.*vfork.*exited normally.*$gdb_prompt " {
 	  setup_kfail "gdb/14762" *-*-*
 	  fail $test

More information about the Gdb-patches mailing list