[PATCH 1/2] [gdb/testsuite] Fix FAIL in gdb.threads/fork-and-threads.exp

Tom de Vries tdevries@suse.de
Tue Oct 26 23:37:09 GMT 2021


As reported in PR26272, when running test-case
gdb.threads/fork-and-threads.exp on a VM with openSUSE Tumbleweed, with the VM
bound to 1 cpu with 75% execution cap, I get:
...
[Inferior 1 (process 21928) exited normally]PASS: \
  gdb.threads/fork-plus-threads.exp: detach-on-fork=off: inferior 1 exited
PASS: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: \
  no failure to remove breakpoints
PASS: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: \
  no spurious thread stop
^M
info threads^M
  Id   Target Id                         Frame ^M
  11.11 Thread 0x7ffff3470700 (LWP 22041) (running)^M
^M
No selected thread.  See `help thread'.^M
(gdb) FAIL: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: \
  no threads left
[Inferior 11 (process 21990) exited normally]^M
info inferiors^M
  Num  Description       Connection           Executable        ^M
* 1    <null>                                 fork-plus-threads ^M
  11   <null>                                 fork-plus-threads ^M
(gdb) FAIL: gdb.threads/fork-plus-threads.exp: detach-on-fork=off: \
  only inferior 1 left (the program exited)
...

The initial process (inferior 1) creates 10 child processes, and then waits on
the child processes.  Consequently, the initial process is also the last
process to exit.

However, in the log above we see:
...
[Inferior 1 (process 21928) exited normally]
  ...
[Inferior 11 (process 21990) exited normally]
...
This seems counter-intuitive: if inferior 1 is the last to exit, shouldn't we
see it last?

However, looking at the debug infrun log:
...
[infrun] fetch_inferior_event: enter
  [infrun] scoped_disable_commit_resumed: reason=handling event
  [infrun] do_target_wait: Found 2 inferiors, starting at #0
  [infrun] random_pending_event_thread: None found.
  [infrun] print_target_wait_results: target_wait (-1.0.0 [process -1], status) =
  [infrun] print_target_wait_results:   17202.17202.0 [Thread 0x7ffff7c79740 (LWP 17202)],
  [infrun] print_target_wait_results:   status->kind = exited, status = 0
  [infrun] handle_inferior_event: status->kind = exited, status = 0
[Inferior 1 (process 17202) exited normally]
  [infrun] stop_waiting: stop_waiting
  [infrun] reset: reason=handling event
  [infrun] maybe_set_commit_resumed_all_targets: enabling commit-resumed for target native
  [infrun] maybe_call_commit_resumed_all_targets: calling commit_resumed for target native
[infrun] fetch_inferior_event: exit
[infrun] fetch_inferior_event: enter
  [infrun] scoped_disable_commit_resumed: reason=handling event
  [infrun] random_pending_event_thread: None found.
  [infrun] print_target_wait_results: target_wait (-1.0.0 [process -1], status) =
  [infrun] print_target_wait_results:   17215.17215.0 [Thread 0x7ffff7c79740 (LWP 17215)],
  [infrun] print_target_wait_results:   status->kind = exited, status = 0
  [infrun] handle_inferior_event: status->kind = exited, status = 0
[Inferior 11 (process 17215) exited normally]
...
this seems plausible.

Doing a waitpid with a pid of -1 will wait for any child process, and if
both inferior 1 and 11 have exited, and not yet been reaped, waitpid may
return any of the two.

Fix the first FAIL by waiting for all inferiors to exit, rather than waiting
for inferior 1 to exit, assuming it's the last.

Tested on x86_64-linux.
---
 .../gdb.threads/fork-plus-threads.exp         | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/fork-plus-threads.exp b/gdb/testsuite/gdb.threads/fork-plus-threads.exp
index 2300279254e..3e3b84114b1 100644
--- a/gdb/testsuite/gdb.threads/fork-plus-threads.exp
+++ b/gdb/testsuite/gdb.threads/fork-plus-threads.exp
@@ -33,6 +33,7 @@ proc do_test { detach-on-fork } {
     global GDBFLAGS
     global srcfile testfile
     global gdb_prompt
+    global decimal
 
     set saved_gdbflags $GDBFLAGS
     set GDBFLAGS [concat $GDBFLAGS " -ex \"set non-stop on\""]
@@ -50,6 +51,12 @@ proc do_test { detach-on-fork } {
     }
 
     gdb_test_no_output "set detach-on-fork ${detach-on-fork}"
+    if { ${detach-on-fork} == "on" } {
+	set expected_exits 1
+    } else {
+	set expected_exits 11
+    }
+
     set test "continue &"
     gdb_test_multiple $test $test {
 	-re "$gdb_prompt " {
@@ -76,8 +83,8 @@ proc do_test { detach-on-fork } {
     set saw_cannot_remove_breakpoints 0
     set saw_thread_stopped 0
 
-    set test "inferior 1 exited"
-    gdb_test_multiple "" $test {
+    set nr_exits 0
+    gdb_test_multiple "" "last inferior exited" {
 	-re "Cannot remove breakpoints" {
 	    set saw_cannot_remove_breakpoints 1
 	    exp_continue
@@ -94,8 +101,12 @@ proc do_test { detach-on-fork } {
 	    # Avoid timeout with check-read1
 	    exp_continue
 	}
-	-re "Inferior 1 \(\[^\r\n\]+\) exited normally" {
-	    pass $test
+	-re "Inferior $decimal \(\[^\r\n\]+\) exited normally" {
+	    incr nr_exits
+	    if { $nr_exits < $expected_exits } {
+		exp_continue
+	    }
+	    pass $gdb_test_name
 	}
     }
 

base-commit: f85dcfc3af9cf7c2859241253f1d37b1133abea2
-- 
2.26.2



More information about the Gdb-patches mailing list