* [PATCH 0/2] [gdb/testsuite] Two gdb.threads patches
@ 2026-07-23 11:40 Tom de Vries
2026-07-23 11:40 ` [PATCH 1/2] [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp Tom de Vries
2026-07-23 11:40 ` [PATCH 2/2] [gdb/testsuite] Fix timeout in gdb.threads/vfork-multi-inferior.exp Tom de Vries
0 siblings, 2 replies; 6+ messages in thread
From: Tom de Vries @ 2026-07-23 11:40 UTC (permalink / raw)
To: gdb-patches
Two patches fixing gdb.threads test-cases.
Tom de Vries (2):
[gdb/testsuite] Fix race in gdb.threads/leader-exit.exp
[gdb/testsuite] Fix timeout in gdb.threads/vfork-multi-inferior.exp
gdb/testsuite/gdb.threads/leader-exit.c | 4 ++++
gdb/testsuite/gdb.threads/leader-exit.exp | 22 +++++++++++++++++++
gdb/testsuite/gdb.threads/non-ldr-exc-2.c | 5 +++++
gdb/testsuite/gdb.threads/non-ldr-exc-2.exp | 22 +++++++++++++++++++
.../gdb.threads/vfork-multi-inferior.exp | 2 +-
5 files changed, 54 insertions(+), 1 deletion(-)
base-commit: 39fc0cc4aa6f82a73b9eac6b8739895484ab269f
--
2.51.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp
2026-07-23 11:40 [PATCH 0/2] [gdb/testsuite] Two gdb.threads patches Tom de Vries
@ 2026-07-23 11:40 ` Tom de Vries
2026-07-24 17:49 ` Keith Seitz
2026-07-23 11:40 ` [PATCH 2/2] [gdb/testsuite] Fix timeout in gdb.threads/vfork-multi-inferior.exp Tom de Vries
1 sibling, 1 reply; 6+ messages in thread
From: Tom de Vries @ 2026-07-23 11:40 UTC (permalink / raw)
To: gdb-patches
On aarch64-linux, when running test-case gdb.threads/leader-exit.exp with
"taskset -c 0", 3 out of 10 times I run into:
...
(gdb) continue
Continuing.
[New Thread 0xfffff7d1f160 (LWP 62010) (id 2)]
[Switching to thread 2 (Thread 0xfffff7d1f160 (LWP 62010))]
Thread 2 "leader-exit" hit Breakpoint 2, start (arg=0x0) at leader-exit.c:32
32 sleep (10); /* break-here */
(gdb) PASS: gdb.threads/leader-exit.exp: continue to breakpoint: break-here
info threads
Id Target Id Frame
1 Thread 0xfffff7fe8020 (LWP 62008) "leader-exit" (Exiting) \
0x0000fffff7d46fa0 in __libc_start_call_main () from /lib64/libc.so.6
* 2 Thread 0xfffff7d1f160 (LWP 62010) "leader-exit" \
start (arg=0x0) at leader-exit.c:32
(gdb) FAIL: gdb.threads/leader-exit.exp: single thread has been left
...
In a passing version, the continue produces a "Thread exited" message, but
that's missing here.
The problem is that after the pthread_join is executed:
...
i = pthread_join (main_thread, NULL);
...
sleep (10); /* break-here */
...
there's a race between:
- the breakpoint at break-here triggering, and
- the "Thread exited" message for the main thread being reported.
Fix this by:
- adding a loop before the break location
- waiting in the loop until the "Thread exited" message is seen
- sending ^C to get a prompt
- setting a variable to exit the loop
Likewise in gdb.threads/non-ldr-exc-2.exp.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34425
---
gdb/testsuite/gdb.threads/leader-exit.c | 4 ++++
gdb/testsuite/gdb.threads/leader-exit.exp | 22 +++++++++++++++++++++
gdb/testsuite/gdb.threads/non-ldr-exc-2.c | 5 +++++
gdb/testsuite/gdb.threads/non-ldr-exc-2.exp | 22 +++++++++++++++++++++
4 files changed, 53 insertions(+)
diff --git a/gdb/testsuite/gdb.threads/leader-exit.c b/gdb/testsuite/gdb.threads/leader-exit.c
index bd546d009cd..b24817e8a14 100644
--- a/gdb/testsuite/gdb.threads/leader-exit.c
+++ b/gdb/testsuite/gdb.threads/leader-exit.c
@@ -21,6 +21,8 @@
static volatile pthread_t main_thread;
+static volatile int wait_for_exit = 1;
+
static void *
start (void *arg)
{
@@ -28,6 +30,8 @@ start (void *arg)
i = pthread_join (main_thread, NULL);
assert (i == 0);
+ while (wait_for_exit)
+ usleep (100 * 1000);
sleep (10); /* break-here */
return arg;
diff --git a/gdb/testsuite/gdb.threads/leader-exit.exp b/gdb/testsuite/gdb.threads/leader-exit.exp
index b5e6f558ac7..22f27d2d6e8 100644
--- a/gdb/testsuite/gdb.threads/leader-exit.exp
+++ b/gdb/testsuite/gdb.threads/leader-exit.exp
@@ -30,6 +30,28 @@ if {![runto_main]} {
return
}
+# Wait for the "Thread exited" message.
+set re_thread_exited {\[Thread [^\r\n]+ exited\]}
+set saw_thread_exited 0
+gdb_test_multiple "continue" "continue to thread exited" {
+ -re $re_thread_exited {
+ set saw_thread_exited 1
+ # Get a prompt.
+ send_gdb "\003"
+ exp_continue
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
+ }
+}
+gdb_assert {$saw_thread_exited} "thread exited"
+if {!$saw_thread_exited} {
+ return
+}
+
+# Let the inferior to exit the wait_for_exit loop.
+gdb_test_no_output "set var wait_for_exit = 0"
+
gdb_breakpoint [gdb_get_line_number "break-here"]
gdb_continue_to_breakpoint "break-here" ".* break-here .*"
diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-2.c b/gdb/testsuite/gdb.threads/non-ldr-exc-2.c
index b05479be01f..a9e81dfa495 100644
--- a/gdb/testsuite/gdb.threads/non-ldr-exc-2.c
+++ b/gdb/testsuite/gdb.threads/non-ldr-exc-2.c
@@ -26,6 +26,8 @@ static const char *image;
static volatile pthread_t main_thread;
static char *argv1 = "go away";
+static volatile int wait_for_exit = 1;
+
static void *
thread_execler (void *arg)
{
@@ -34,6 +36,9 @@ thread_execler (void *arg)
i = pthread_join (main_thread, NULL);
assert (i == 0);
+ while (wait_for_exit)
+ usleep (100 * 1000);
+
/* Exec ourselves again. */
if (execl (image, image, argv1, NULL) == -1) /* break-here */
{
diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
index ead262cc2b5..dfc34f42afe 100644
--- a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
+++ b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
@@ -37,6 +37,28 @@ proc do_test { lock_sched nonstop } {
return -1
}
+ # Wait for the "Thread exited" message.
+ set re_thread_exited {\[Thread [^\r\n]+ exited\]}
+ set saw_thread_exited 0
+ gdb_test_multiple "continue" "continue to thread exited" {
+ -re $re_thread_exited {
+ set saw_thread_exited 1
+ # Get a prompt.
+ send_gdb "\003"
+ exp_continue
+ }
+ -re -wrap "" {
+ pass $gdb_test_name
+ }
+ }
+ gdb_assert {$saw_thread_exited} "thread exited"
+ if {!$saw_thread_exited} {
+ return
+ }
+
+ # Let the inferior to exit the wait_for_exit loop.
+ gdb_test_no_output "set var wait_for_exit = 0"
+
gdb_breakpoint [gdb_get_line_number "break-here"]
gdb_continue_to_breakpoint "break-here" ".* break-here .*"
--
2.51.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] [gdb/testsuite] Fix timeout in gdb.threads/vfork-multi-inferior.exp
2026-07-23 11:40 [PATCH 0/2] [gdb/testsuite] Two gdb.threads patches Tom de Vries
2026-07-23 11:40 ` [PATCH 1/2] [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp Tom de Vries
@ 2026-07-23 11:40 ` Tom de Vries
2026-07-24 17:52 ` Keith Seitz
1 sibling, 1 reply; 6+ messages in thread
From: Tom de Vries @ 2026-07-23 11:40 UTC (permalink / raw)
To: gdb-patches
With test-case gdb.threads/vfork-multi-inferior.exp I get either:
...
(gdb) run &
Starting program: vfork-multi-inferior-sleep
(gdb) PASS: $exp: method=non-stop: run inferior 2
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
inferior 1
[Switching to inferior 1 [<null>] (<noexec>)]
(gdb) PASS: $exp: method=non-stop: inferior 1
...
or:
...
(gdb) run &
Starting program: vfork-multi-inferior-sleep
(gdb) PASS: $exp: method=non-stop: run inferior 2
inferior 1^M
[Switching to inferior 1 [<null>] (<noexec>)]^M
(gdb) PASS: $exp: method=non-stop: inferior 1
[Thread debugging using libthread_db enabled]^M
Using host libthread_db library "/lib64/libthread_db.so.1".^M
...
With a 16.3-based package on aarch64-linux, I ran into:
...
(gdb) run &
Starting program: vfork-multi-inferior-sleep
(gdb) PASS: $exp: method=non-stop: run inferior 2
inferior 1
[Switching to inferior 1 [<null>] (<noexec>)]
(gdb) [Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
FAIL: $exp: method=non-stop: inferior 1
(timeout)
...
Unfortunately I have not been able to reproduce this.
Fix this using -no-prompt-anchor.
See also commit 5f69c00a6e0 ("[gdb/testsuite] Fix timeout in
gdb.base/async-shell.exp").
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34427
---
gdb/testsuite/gdb.threads/vfork-multi-inferior.exp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/testsuite/gdb.threads/vfork-multi-inferior.exp b/gdb/testsuite/gdb.threads/vfork-multi-inferior.exp
index e258ec719e9..f6c90bf0655 100644
--- a/gdb/testsuite/gdb.threads/vfork-multi-inferior.exp
+++ b/gdb/testsuite/gdb.threads/vfork-multi-inferior.exp
@@ -86,7 +86,7 @@ proc do_test {method} {
}
# Start the first inferior.
- gdb_test "inferior 1" "Switching to inferior 1 .*"
+ gdb_test -no-prompt-anchor "inferior 1" "Switching to inferior 1 .*"
gdb_file_cmd ${::binfile}
gdb_test "break should_break_here" "Breakpoint $::decimal at .*"
gdb_test "start" "Thread 1.1 .* hit Temporary breakpoint.*" \
--
2.51.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp
2026-07-23 11:40 ` [PATCH 1/2] [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp Tom de Vries
@ 2026-07-24 17:49 ` Keith Seitz
2026-07-25 7:03 ` Tom de Vries
0 siblings, 1 reply; 6+ messages in thread
From: Keith Seitz @ 2026-07-24 17:49 UTC (permalink / raw)
To: Tom de Vries, gdb-patches
Hi,
On 7/23/26 4:40 AM, Tom de Vries wrote:
>
> The problem is that after the pthread_join is executed:
> ...
> i = pthread_join (main_thread, NULL);
> ...
>
> sleep (10); /* break-here */
> ...
> there's a race between:
> - the breakpoint at break-here triggering, and
> - the "Thread exited" message for the main thread being reported.
While I cannot reproduce this on my local hardware, your analysis
is sound.
> Fix this by:
> - adding a loop before the break location
> - waiting in the loop until the "Thread exited" message is seen
> - sending ^C to get a prompt
> - setting a variable to exit the loop
>
> Likewise in gdb.threads/non-ldr-exc-2.exp.
Sounds like a plan!
> diff --git a/gdb/testsuite/gdb.threads/leader-exit.exp b/gdb/testsuite/gdb.threads/leader-exit.exp
> index b5e6f558ac7..22f27d2d6e8 100644
> --- a/gdb/testsuite/gdb.threads/leader-exit.exp
> +++ b/gdb/testsuite/gdb.threads/leader-exit.exp
> @@ -30,6 +30,28 @@ if {![runto_main]} {
> return
> }
>
> +# Wait for the "Thread exited" message.
> +set re_thread_exited {\[Thread [^\r\n]+ exited\]}
> +set saw_thread_exited 0
> +gdb_test_multiple "continue" "continue to thread exited" {
> + -re $re_thread_exited {
> + set saw_thread_exited 1
> + # Get a prompt.
> + send_gdb "\003"
> + exp_continue
> + }
> + -re -wrap "" {
> + pass $gdb_test_name
> + }
> +}
> +gdb_assert {$saw_thread_exited} "thread exited"
> +if {!$saw_thread_exited} {
> + return
> +}
> +
> +# Let the inferior to exit the wait_for_exit loop.
This comment got a bit jumbled. Superfluous "to"?
> +gdb_test_no_output "set var wait_for_exit = 0"
> +
> gdb_breakpoint [gdb_get_line_number "break-here"]
> gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>
> diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
> index ead262cc2b5..dfc34f42afe 100644
> --- a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
> +++ b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
> @@ -37,6 +37,28 @@ proc do_test { lock_sched nonstop } {
> return -1
> }
>
> + # Wait for the "Thread exited" message.
> + set re_thread_exited {\[Thread [^\r\n]+ exited\]}
> + set saw_thread_exited 0
> + gdb_test_multiple "continue" "continue to thread exited" {
> + -re $re_thread_exited {
> + set saw_thread_exited 1
> + # Get a prompt.
> + send_gdb "\003"
> + exp_continue
> + }
> + -re -wrap "" {
> + pass $gdb_test_name
> + }
> + }
> + gdb_assert {$saw_thread_exited} "thread exited"
> + if {!$saw_thread_exited} {
> + return
> + }
> +
> + # Let the inferior to exit the wait_for_exit loop.
Same nit in this comment.
Question: Since this test file now relies on sending the target
an interrupt, does it also need the same "require" on gdb,nointerrupts
that leader-exit.exp has?
Reviewed-By: Keith Seitz <keiths@redhat.com>
Keith
> + gdb_test_no_output "set var wait_for_exit = 0"
> +
> gdb_breakpoint [gdb_get_line_number "break-here"]
> gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] [gdb/testsuite] Fix timeout in gdb.threads/vfork-multi-inferior.exp
2026-07-23 11:40 ` [PATCH 2/2] [gdb/testsuite] Fix timeout in gdb.threads/vfork-multi-inferior.exp Tom de Vries
@ 2026-07-24 17:52 ` Keith Seitz
0 siblings, 0 replies; 6+ messages in thread
From: Keith Seitz @ 2026-07-24 17:52 UTC (permalink / raw)
To: Tom de Vries, gdb-patches
Hi,
On 7/23/26 4:40 AM, Tom de Vries wrote:
> Unfortunately I have not been able to reproduce this.
>
Nor am I...
> Fix this using -no-prompt-anchor.
>
> See also commit 5f69c00a6e0 ("[gdb/testsuite] Fix timeout in
> gdb.base/async-shell.exp").
I agree this is an established paradigm and harmless enough.
Thank you for your tireless efforts to clean up the test suite.
Reviewed-By: Keith Seitz <keiths@redhat.com>
Keith
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp
2026-07-24 17:49 ` Keith Seitz
@ 2026-07-25 7:03 ` Tom de Vries
0 siblings, 0 replies; 6+ messages in thread
From: Tom de Vries @ 2026-07-25 7:03 UTC (permalink / raw)
To: Keith Seitz, gdb-patches
On 7/24/26 7:49 PM, Keith Seitz wrote:
> Hi,
>
> On 7/23/26 4:40 AM, Tom de Vries wrote:
>>
>> The problem is that after the pthread_join is executed:
>> ...
>> i = pthread_join (main_thread, NULL);
>> ...
>>
>> sleep (10); /* break-here */
>> ...
>> there's a race between:
>> - the breakpoint at break-here triggering, and
>> - the "Thread exited" message for the main thread being reported.
>
> While I cannot reproduce this on my local hardware, your analysis
> is sound.
>
>> Fix this by:
>> - adding a loop before the break location
>> - waiting in the loop until the "Thread exited" message is seen
>> - sending ^C to get a prompt
>> - setting a variable to exit the loop
>>
>> Likewise in gdb.threads/non-ldr-exc-2.exp.
>
> Sounds like a plan!
>
>> diff --git a/gdb/testsuite/gdb.threads/leader-exit.exp b/gdb/
>> testsuite/gdb.threads/leader-exit.exp
>> index b5e6f558ac7..22f27d2d6e8 100644
>> --- a/gdb/testsuite/gdb.threads/leader-exit.exp
>> +++ b/gdb/testsuite/gdb.threads/leader-exit.exp
>> @@ -30,6 +30,28 @@ if {![runto_main]} {
>> return
>> }
>> +# Wait for the "Thread exited" message.
>> +set re_thread_exited {\[Thread [^\r\n]+ exited\]}
>> +set saw_thread_exited 0
>> +gdb_test_multiple "continue" "continue to thread exited" {
>> + -re $re_thread_exited {
>> + set saw_thread_exited 1
>> + # Get a prompt.
>> + send_gdb "\003"
>> + exp_continue
>> + }
>> + -re -wrap "" {
>> + pass $gdb_test_name
>> + }
>> +}
>> +gdb_assert {$saw_thread_exited} "thread exited"
>> +if {!$saw_thread_exited} {
>> + return
>> +}
>> +
>> +# Let the inferior to exit the wait_for_exit loop.
>
> This comment got a bit jumbled. Superfluous "to"?
>
>> +gdb_test_no_output "set var wait_for_exit = 0"
>> +
>> gdb_breakpoint [gdb_get_line_number "break-here"]
>> gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>> diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp b/gdb/
>> testsuite/gdb.threads/non-ldr-exc-2.exp
>> index ead262cc2b5..dfc34f42afe 100644
>> --- a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
>> +++ b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp
>> @@ -37,6 +37,28 @@ proc do_test { lock_sched nonstop } {
>> return -1
>> }
>> + # Wait for the "Thread exited" message.
>> + set re_thread_exited {\[Thread [^\r\n]+ exited\]}
>> + set saw_thread_exited 0
>> + gdb_test_multiple "continue" "continue to thread exited" {
>> + -re $re_thread_exited {
>> + set saw_thread_exited 1
>> + # Get a prompt.
>> + send_gdb "\003"
>> + exp_continue
>> + }
>> + -re -wrap "" {
>> + pass $gdb_test_name
>> + }
>> + }
>> + gdb_assert {$saw_thread_exited} "thread exited"
>> + if {!$saw_thread_exited} {
>> + return
>> + }
>> +
>> + # Let the inferior to exit the wait_for_exit loop.
>
> Same nit in this comment.
>
Hi Keith,
fixed both nits.
> Question: Since this test file now relies on sending the target
> an interrupt, does it also need the same "require" on gdb,nointerrupts
> that leader-exit.exp has?
>
Thanks for spotting that. I've added this, and pushed.
Thanks for the reviews,
- Tom
> Reviewed-By: Keith Seitz <keiths@redhat.com>
>
> Keith
>
>> + gdb_test_no_output "set var wait_for_exit = 0"
>> +
>> gdb_breakpoint [gdb_get_line_number "break-here"]
>> gdb_continue_to_breakpoint "break-here" ".* break-here .*"
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-07-25 7:04 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-23 11:40 [PATCH 0/2] [gdb/testsuite] Two gdb.threads patches Tom de Vries
2026-07-23 11:40 ` [PATCH 1/2] [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp Tom de Vries
2026-07-24 17:49 ` Keith Seitz
2026-07-25 7:03 ` Tom de Vries
2026-07-23 11:40 ` [PATCH 2/2] [gdb/testsuite] Fix timeout in gdb.threads/vfork-multi-inferior.exp Tom de Vries
2026-07-24 17:52 ` Keith Seitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox