* [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
* 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 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
* [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 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
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