public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] gdb/testsuite: fix intermittent failure in gdb.base/vfork-follow-parent.exp
@ 2022-04-05 12:15 Simon Marchi
  0 siblings, 0 replies; only message in thread
From: Simon Marchi @ 2022-04-05 12:15 UTC (permalink / raw)
  To: gdb-cvs

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

commit b8b5466f0dd1c993015a767f1fe4f294f79b494f
Author: Simon Marchi <simon.marchi@efficios.com>
Date:   Mon Apr 4 14:45:36 2022 -0400

    gdb/testsuite: fix intermittent failure in gdb.base/vfork-follow-parent.exp
    
    Tom de Vries reported some failures in this test:
    
        continue
        Continuing.
        [New inferior 2 (process 14967)]
    
        Thread 1.1 "vfork-follow-pa" hit Breakpoint 2, break_parent () at /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/vfork-follow-parent.c:23
        23  }
        (gdb) FAIL: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: continue to end of inferior 2
        inferior 1
        [Switching to inferior 1 [process 14961] (/home/vries/gdb_versions/devel/build/gdb/testsuite/outputs/gdb.base/vfork-follow-parent/vfork-follow-parent)]
        [Switching to thread 1.1 (process 14961)]
        #0  break_parent () at /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.base/vfork-follow-parent.c:23
        23  }
        (gdb) PASS: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: inferior 1
        continue
        Continuing.
        [Inferior 2 (process 14967) exited normally]
        (gdb) FAIL: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: continue to break_parent (the program exited)
    
    Here, we continue both the vfork parent and child, since
    schedule-multiple is on.  The child exits, which un-freezes the parent
    and makes an exit event available to GDB.  We expect GDB to consume this
    exit event and present it to the user.  Here, we see that GDB shows the
    parent hitting a breakpoint before showing the child exit.
    
    Because of the vfork, we know that chronologically, the child exiting
    must have happend before the parent hitting a breakpoint.  However,
    scheduling being what it is, it is possible for the parent to un-freeze
    and exit quickly, such that when GDB pulls events out of the kernel,
    exit events for both processes are available.  And then, GDB may chose
    at random to return the one for the parent first.  This is what I
    imagine what causes the failure shown above.
    
    We could change the test to expect both possible outcomes, but I wanted
    to avoid complicating the .exp file that way.  Instead, add a variable
    that the parent loops on that we set only after we confirmed the exit of
    the child.  That should ensure that the order is always the same.
    
    Note that I wasn't able to reproduce the failure, so I can't tell if
    this fix really fixes the problem.
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29021
    Change-Id: Ibc8e527e0e00dac54b22021fe4d9d8ab0f3b28ad

Diff:
---
 gdb/testsuite/gdb.base/vfork-follow-parent.c   | 14 +++++++++++++-
 gdb/testsuite/gdb.base/vfork-follow-parent.exp |  2 ++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gdb/testsuite/gdb.base/vfork-follow-parent.c b/gdb/testsuite/gdb.base/vfork-follow-parent.c
index f4face70f6e..5fdd051523a 100644
--- a/gdb/testsuite/gdb.base/vfork-follow-parent.c
+++ b/gdb/testsuite/gdb.base/vfork-follow-parent.c
@@ -17,6 +17,8 @@
 
 #include <unistd.h>
 
+static volatile int unblock_parent = 0;
+
 static void
 break_parent (void)
 {
@@ -25,8 +27,18 @@ break_parent (void)
 int
 main (void)
 {
+  alarm (30);
+
   if (vfork () != 0)
-    break_parent ();
+    {
+      /* We want to guarantee that GDB processes the child exit event before
+	 the parent's breakpoint hit event.  Make the parent wait on this
+	 variable that is eventually set by the test.  */
+      while (!unblock_parent)
+	usleep (1000);
+
+      break_parent ();
+    }
   else
     _exit (0);
 
diff --git a/gdb/testsuite/gdb.base/vfork-follow-parent.exp b/gdb/testsuite/gdb.base/vfork-follow-parent.exp
index ded87548a9e..1ffc54e6293 100644
--- a/gdb/testsuite/gdb.base/vfork-follow-parent.exp
+++ b/gdb/testsuite/gdb.base/vfork-follow-parent.exp
@@ -56,6 +56,7 @@ proc do_test { resolution_method } {
     if { $resolution_method == "detach-on-fork" } {
 	# Make GDB detach the child.
 	gdb_test "set detach-on-fork on"
+	gdb_test "print unblock_parent = 1" " = 1"
     } elseif { $resolution_method == "schedule-multiple" } {
 	# Make GDB resume both inferiors.  The parent is blocked while the
 	# children executes, so the continue will make the child reach the
@@ -64,6 +65,7 @@ proc do_test { resolution_method } {
 	gdb_test "continue" "$::inferior_exited_re normally.*" \
 	    "continue to end of inferior 2"
 	gdb_test "inferior 1" ".*Switching to inferior 1.*"
+	gdb_test "print unblock_parent = 1" " = 1"
     } else {
 	error "invalid resolution method: $resolution_method"
     }


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

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

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-05 12:15 [binutils-gdb] gdb/testsuite: fix intermittent failure in gdb.base/vfork-follow-parent.exp 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).