[PATCH] vfork: follow-fork child, detach-on-fork on: Fix dangling "is vfork parent of".

Pedro Alves palves@redhat.com
Mon Nov 5 18:58:00 GMT 2012


$ ./gdb -q ./testsuite/gdb.base/foll-vfork -ex "cd testsuite" -ex "set follow-fork child" -ex "set detach-on-fork on"
Python Exception <type 'exceptions.ImportError'> No module named gdb:

(gdb) r
Starting program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.base/foll-vfork
[New process 2497]
I'm the child!
I'm the proud parent of child #2497!
process 2497 is executing new program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.base/vforked-prog
Hello from vforked-prog...
[Inferior 2 (process 2497) exited normally]
(gdb) info inferiors
  Num  Description       Executable
* 2    <null>            /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.base/vforked-prog
  1    <null>            /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.base/vforked-prog
        is vfork parent of inferior 2
	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(gdb)

The "is vfork parent of inferior" part is stale.  The fix is to clear
the struct inferior's vfork child pointer on inferior detach.
exit/kill/etc. should also clear them, so the fix goes to the central
exit_inferior_1, where the vfork parent pointer is already cleared.
While at it, the pending_detach flag is also not being cleared.

There are other problems with this use case.  inferior 1's executable
shouldn't have changed to vforked-prog, for one (I'll file a PR).  The
"detach-on-fork" case should maybe be hiding the parent inferior
behind the scenes until it is detached (like it was in the old days,
before multi-inferior/exec, except it was then a hack in linux-nat.c).
It seems likely that even with such change we need to break the
parent/child relation like in this patch, so I'm still pushing in this
particular fix.  The test naturaly relies on both inferiors appearing
on "info inferiors".  If we ever hide the pending-detach parent from
view, we'll likely introduce a "main info inferiors" command that
lists all inferiors including the hidden ones, which we can then use
to exercise this same issue with trivial changes to the .exp file.

Tested on AMD64 Fedora 17, and applied.

gdb/
2012-11-05  Pedro Alves  <palves@redhat.com>

	* inferior.c (exit_inferior_1): Clear 'vfork_parent' in the vfork
	child.  Clear 'pending_detach'.
	* infrun.c (handle_vfork_child_exec_or_exit): Clear
	'pending_detach' in the vfork parent.

gdb/testsuite/
2012-11-05  Pedro Alves  <palves@redhat.com>

	* gdb.base/foll-vfork.exp (vfork_relations_in_info_inferiors): New
	procedure.
	(do_vfork_and_follow_child_tests_exec)
	(do_vfork_and_follow_child_tests_exit): Call it.
---
 gdb/inferior.c                        |    6 +++
 gdb/infrun.c                          |    2 +
 gdb/testsuite/gdb.base/foll-vfork.exp |   66 +++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)

diff --git a/gdb/inferior.c b/gdb/inferior.c
index f45058a..f46e1e3 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -266,9 +266,15 @@ exit_inferior_1 (struct inferior *inftoex, int silent)
       inf->vfork_parent->vfork_child = NULL;
       inf->vfork_parent = NULL;
     }
+  if (inf->vfork_child != NULL)
+    {
+      inf->vfork_child->vfork_parent = NULL;
+      inf->vfork_child = NULL;
+    }
 
   inf->has_exit_code = 0;
   inf->exit_code = 0;
+  inf->pending_detach = 0;
 }
 
 void
diff --git a/gdb/infrun.c b/gdb/infrun.c
index ab5aacf..3d6eccd 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -663,6 +663,8 @@ handle_vfork_child_exec_or_exit (int exec)
 
 	  /* follow-fork child, detach-on-fork on.  */
 
+	  inf->vfork_parent->pending_detach = 0;
+
 	  if (!exec)
 	    {
 	      /* If we're handling a child exit, then inferior_ptid
diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp
index 0b2eee6..58e92c4 100644
--- a/gdb/testsuite/gdb.base/foll-vfork.exp
+++ b/gdb/testsuite/gdb.base/foll-vfork.exp
@@ -388,6 +388,58 @@ proc tcatch_vfork_then_child_follow_exit {} {
    exec sleep 1
 }}
 
+proc vfork_relations_in_info_inferiors { variant } {
+  with_test_prefix "vfork relations in info inferiors" {
+   global gdb_prompt
+
+   setup_gdb
+
+   gdb_test_no_output "set follow-fork child"
+
+   set test "step over vfork"
+   gdb_test_multiple "next" $test {
+       -re "Attaching after .* vfork to child.*if \\(pid == 0\\).*$gdb_prompt " {
+	   pass "$test"
+       }
+   }
+
+   gdb_test "info inferiors" \
+       ".*is vfork child of inferior 1.*is vfork parent of inferior 2" \
+       "info inferiors shows vfork parent/child relation"
+
+   if { $variant == "exec" } {
+       global srcfile2
+
+       set linenum [gdb_get_line_number "printf(\"Hello from vforked-prog" ${srcfile2}]
+       set test "continue to bp"
+       gdb_test_multiple "continue" $test {
+	   -re ".*xecuting new program.*Breakpoint.*vforked-prog.c:${linenum}.*$gdb_prompt " {
+	       pass $test
+	   }
+       }
+   } else {
+       set test "continue to child exit"
+       gdb_test_multiple "continue" $test {
+	   -re "exited normally.*$gdb_prompt " {
+	       pass $test
+	   }
+       }
+   }
+
+   set test "vfork relation no longer appears in info inferiors"
+   gdb_test_multiple "info inferiors" $test {
+       -re "is vfork child of inferior 1.*$gdb_prompt $" {
+	   fail $test
+       }
+       -re "is vfork parent of inferior 2.*$gdb_prompt $" {
+	   fail $test
+       }
+       -re "$gdb_prompt $" {
+	   pass $test
+       }
+   }
+}}
+
 proc do_vfork_and_follow_parent_tests {} {
    global gdb_prompt
 
@@ -435,6 +487,13 @@ proc do_vfork_and_follow_child_tests_exec {} {
    # catchpoints.
    # ??rehrauer: NYI.  Will add testpoints here when implemented.
    #
+
+   # Step over a vfork in the child, do "info inferiors" and check the
+   # parent/child relation is displayed.  Run the child over the exec,
+   # and confirm the relation is no longer displayed in "info
+   # inferiors".
+   #
+   vfork_relations_in_info_inferiors "exec"
 }
 
 proc do_vfork_and_follow_child_tests_exit {} {
@@ -446,6 +505,13 @@ proc do_vfork_and_follow_child_tests_exit {} {
    # Try catching a vfork, and stepping out to the child.
    #
    tcatch_vfork_then_child_follow_exit
+
+   # Step over a vfork in the child, do "info inferiors" and check the
+   # parent/child relation is displayed.  Run the child to completion,
+   # and confirm the relation is no longer displayed in "info
+   # inferiors".
+   #
+   vfork_relations_in_info_inferiors "exit"
 }
 
 with_test_prefix "check vfork support" {



More information about the Gdb-patches mailing list