[v2,gdb/testsuite] Fix timeout in gdb.threads/main-thread-exit-during-detach.exp
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Test passed
|
Commit Message
With a gdb 15.2 based package and test-case
gdb.threads/main-thread-exit-during-detach.exp, I ran into:
...
(gdb) attach 23068
Attaching to program: main-thread-exit-during-detach, process 23068
[New LWP 23080]
...
0x0000ffffb79aa178 in clock_nanosleep@@GLIBC_2.17 () from /lib64/libc.so.6
(gdb) PASS: $exp: spawn_inferior=true: attach to the inferior
p 1 + 2
$1 = 3
(gdb)
Thread 2 "main-thread-exi" stopped.
0x0000ffffb79aa178 in clock_nanosleep@@GLIBC_2.17 () from /lib64/libc.so.6
FAIL: $exp: spawn_inferior=true: p 1 + 2 (timeout)
...
I managed to reproduce this using two timing hacks.
First, we hack display_gdb_prompt to sleep half a second at the end:
...
printf_unfiltered ("%s", actual_gdb_prompt.c_str ());
gdb_flush (gdb_stdout);
}
+ usleep (500 * 1000);
}
...
to make sure expect has time to:
- parse the output of the attach command up until the prompt,
- issue "PASS: $exp: spawn_inferior=true: attach to the inferior", and
- issue "p 1 + 2"
before gdb issues the "Thread ... stopped." message.
Then we hack proc run_test to wait a while between issuing the print command
and parsing the output:
...
- gdb_test "p 1 + 2" " = 3"
+ set cmd "p 1 + 2"
+ send_gdb "$cmd\n"
+ sleep 1
+ gdb_test "" " = 3" $cmd
...
to make sure that gdb has the time to issue the "Thread ... stopped." message
before the output is parsed.
We could fix this by just using -no-prompt-anchor on the print command, but
there's another issue here.
As explained in the test-case, the setup phase is complete if thread 2 is
stopped:
...
# Setup the inferior. When complete the main thread (#1) will
# still be running (due to non-stop mode), while the worker thread
# (#2) will be stopped.
...
The stated goal of the print statement is:
...
# Attaching to a multi-threaded application in non-stop mode
# can result in thread stops being reported after the prompt
# is displayed.
#
# Send a simple command now just to resync the command prompt.
gdb_test "p 1 + 2" " = 3"
...
so the implicit assumption here seems to be that after this gdb_test, thread 2
is in fact stopped.
However, considering that the reported thread stop is the result of a waitpid
call, which is the result of a SIGSTOP arriving at the thread, I don't think
we can make assumptions about when the thread stop will be reported.
We could fix this by trying to detect the "Thread ... stopped." message, but
doing so will make the test-case much more complex, because it may occur
before and after the attach.
So instead, after the attach, loop doing "info thread 2" until the thread is
no longer reported as running:
...
(gdb) attach 8598^M
Attaching to program: main-thread-exit-during-detach, process 8598^M
[New LWP 8608]^M
...
0x00007f23044f1545 in clock_nanosleep@GLIBC_2.2.5 () from /lib64/libc.so.6^M
(gdb) PASS: $exp: spawn_inferior=true: attach to the inferior
info thread 2^M
Id Target Id Frame ^M
2 Thread 0x7f23043ff6c0 (LWP 8608) "main-thread-exi" (running)^M
(gdb) ^M
Thread 2 "main-thread-exi" stopped.^M
0x00007f23044f1545 in clock_nanosleep@GLIBC_2.2.5 () from /lib64/libc.so.6^M
info thread 2^M
Id Target Id Frame ^M
2 Thread 0x7f23043ff6c0 (LWP 8608) "main-thread-exi" 0x00007f23044f1545 \
in clock_nanosleep@GLIBC_2.2.5 () from /lib64/libc.so.6^M
(gdb) PASS: $exp: spawn_inferior=true: Thread 2 stopped
...
Tested on x86_64-linux.
PR testsuite/32798
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32798
---
.../main-thread-exit-during-detach.exp | 29 +++++++++++++++++--
1 file changed, 26 insertions(+), 3 deletions(-)
base-commit: 82455bdab80f9a4d4f94a6e8590a1bdc58c4010e
Comments
Hi Tom,
On Wednesday, March 19, 2025 10:14 AM, Tom de Vries wrote:
> With a gdb 15.2 based package and test-case
> gdb.threads/main-thread-exit-during-detach.exp, I ran into:
> ...
> (gdb) attach 23068
> Attaching to program: main-thread-exit-during-detach, process 23068
> [New LWP 23080]
> ...
> 0x0000ffffb79aa178 in clock_nanosleep@@GLIBC_2.17 () from /lib64/libc.so.6
> (gdb) PASS: $exp: spawn_inferior=true: attach to the inferior
> p 1 + 2
> $1 = 3
> (gdb)
> Thread 2 "main-thread-exi" stopped.
> 0x0000ffffb79aa178 in clock_nanosleep@@GLIBC_2.17 () from /lib64/libc.so.6
> FAIL: $exp: spawn_inferior=true: p 1 + 2 (timeout)
> ...
>
> I managed to reproduce this using two timing hacks.
>
> First, we hack display_gdb_prompt to sleep half a second at the end:
> ...
> printf_unfiltered ("%s", actual_gdb_prompt.c_str ());
> gdb_flush (gdb_stdout);
> }
> + usleep (500 * 1000);
> }
> ...
> to make sure expect has time to:
> - parse the output of the attach command up until the prompt,
> - issue "PASS: $exp: spawn_inferior=true: attach to the inferior", and
> - issue "p 1 + 2"
> before gdb issues the "Thread ... stopped." message.
>
> Then we hack proc run_test to wait a while between issuing the print command
> and parsing the output:
> ...
> - gdb_test "p 1 + 2" " = 3"
> + set cmd "p 1 + 2"
> + send_gdb "$cmd\n"
> + sleep 1
> + gdb_test "" " = 3" $cmd
> ...
> to make sure that gdb has the time to issue the "Thread ... stopped." message
> before the output is parsed.
I confirm that this hack worked to reproduce the failure.
> We could fix this by just using -no-prompt-anchor on the print command, but
> there's another issue here.
>
> As explained in the test-case, the setup phase is complete if thread 2 is
> stopped:
> ...
> # Setup the inferior. When complete the main thread (#1) will
> # still be running (due to non-stop mode), while the worker thread
> # (#2) will be stopped.
> ...
>
> The stated goal of the print statement is:
> ...
> # Attaching to a multi-threaded application in non-stop mode
> # can result in thread stops being reported after the prompt
> # is displayed.
> #
> # Send a simple command now just to resync the command prompt.
> gdb_test "p 1 + 2" " = 3"
> ...
> so the implicit assumption here seems to be that after this gdb_test, thread 2
> is in fact stopped.
>
> However, considering that the reported thread stop is the result of a waitpid
> call, which is the result of a SIGSTOP arriving at the thread, I don't think
> we can make assumptions about when the thread stop will be reported.
>
> We could fix this by trying to detect the "Thread ... stopped." message, but
> doing so will make the test-case much more complex, because it may occur
> before and after the attach.
Is this true? I think the first stop event, which is not printed to the screen
by GDB but handled silently, will trigger the GDB prompt. The second stop event
will be handled then. So, I think the GDB prompt will always be between attach
and the "Thread...stopped" message. Hence, I was wondering if it would be
simpler to handle the case as part of the attach command. For instance like this:
- gdb_test -no-prompt-anchor "attach $testpid" \
- "Attaching to program.*`?$escapedbinfile'?, process $testpid.*" \
- "attach to the inferior"
+ gdb_test_multiple "attach $testpid" "attach to the inferior" -lbl {
+ -re "Attaching to program.*`?$escapedbinfile'?, process $testpid" {
+ exp_continue
+ }
+ -re "\r\n$::gdb_prompt" {
+ exp_continue
+ }
+ -re "\r\nThread \[^\r\n\]* stopped." {
+ pass $gdb_test_name
+ }
+ }
-Baris
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
@@ -76,10 +76,33 @@ proc run_test { spawn_inferior } {
# Attaching to a multi-threaded application in non-stop mode
# can result in thread stops being reported after the prompt
- # is displayed.
+ # is displayed, so the thread may still be reported as running.
#
- # Send a simple command now just to resync the command prompt.
- gdb_test "p 1 + 2" " = 3"
+ # Iterate until the thread is no longer reported as running.
+ set stopped 0
+ set re_running [string_to_regexp "(running)"]
+ for { set i 0 } { $i < 10 } { incr i } {
+ with_test_prefix $i {
+ gdb_test_multiple "info thread 2" "" -no-prompt-anchor {
+ -re -wrap $re_running.* {
+ }
+ -re -wrap "" {
+ set stopped 1
+ }
+ }
+ }
+ if { $stopped } {
+ break
+ }
+
+ # Back off to let gdb and inferior make progress.
+ sleep 1
+ }
+
+ gdb_assert { $stopped } "Thread 2 stopped"
+ if { ! $stopped } {
+ return -1
+ }
# Set thread 1 (the current thread) running again.
gdb_test "continue&"