File gdb-testsuite-fix-fail-in-gdb.threads-fork-and-threads.exp.patch of Package gdb.21950

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

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/testsuite/gdb.threads/fork-plus-threads.exp | 31 ++++++++++++++-----------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/fork-plus-threads.exp b/gdb/testsuite/gdb.threads/fork-plus-threads.exp
index 7fe3c603bcd..8540fbf3082 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\""]
@@ -51,6 +52,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 " {
@@ -77,26 +84,22 @@ 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 {
-	-re "Cannot remove breakpoints" {
+    set nr_exits 0
+    gdb_test_multiple "" "last inferior exited" -lbl {
+	-re "^\r\nCannot remove breakpoints \[^\r\n\]+\\.(?=\r\n)" {
 	    set saw_cannot_remove_breakpoints 1
 	    exp_continue
 	}
-	-re "Thread \[^\r\n\]+ stopped\\." {
+	-re "^\r\n\\\[Thread \[^\r\n\]+ stopped\\.(?=\r\n)" {
 	    set saw_thread_stopped 1
 	    exp_continue
 	}
-	-re "(Thread|LWP) \[^\r\n\]+ exited" {
-	    # Avoid timeout with check-read1
-	    exp_continue
-	}
-	-re "New (Thread|LWP) \[^\r\n\]+" {
-	    # Avoid timeout with check-read1
-	    exp_continue
-	}
-	-re "Inferior 1 \(\[^\r\n\]+\) exited normally" {
-	    pass $test
+	-re "^\r\n\\\[Inferior $decimal \(\[^\r\n\]+\) exited normally\\\](?=\r\n)" {
+	    incr nr_exits
+	    if { $nr_exits < $expected_exits } {
+		exp_continue
+	    }
+	    pass $gdb_test_name
 	}
     }
 
openSUSE Build Service is sponsored by