145 lines
5.3 KiB
Diff
145 lines
5.3 KiB
Diff
|
[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
|
||
|
}
|
||
|
}
|
||
|
|