[binutils-gdb] [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp
Tom de Vries via Gdb-cvs <[email protected]> Sat, 25 Jul 2026 06:59:55 +0000 (GMT)
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D1fba9bb362c6= ca7a0ae30f0fff7d8c1d68f8bdb4 commit 1fba9bb362c6ca7a0ae30f0fff7d8c1d68f8bdb4 Author: Tom de Vries <[email protected]> Date: Sat Jul 25 08:59:51 2026 +0200 [gdb/testsuite] Fix race in gdb.threads/leader-exit.exp =20 On aarch64-linux, when running test-case gdb.threads/leader-exit.exp wi= th "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))] =20 Thread 2 "leader-exit" hit Breakpoint 2, start (arg=3D0x0) at leader-ex= it.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/li= bc.so.6 * 2 Thread 0xfffff7d1f160 (LWP 62010) "leader-exit" \ start (arg=3D0x0) at leader-exit.c:32 (gdb) FAIL: gdb.threads/leader-exit.exp: single thread has been left ... =20 In a passing version, the continue produces a "Thread exited" message, = but that's missing here. =20 The problem is that after the pthread_join is executed: ... i =3D pthread_join (main_thread, NULL); ... =20 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. =20 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 =20 Likewise in gdb.threads/non-ldr-exc-2.exp. =20 Reviewed-By: Keith Seitz <[email protected]> Approved-By: Kevin Buettner <[email protected]> =20 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D34425 Diff: --- gdb/testsuite/gdb.threads/leader-exit.c | 4 ++++ gdb/testsuite/gdb.threads/leader-exit.exp | 24 +++++++++++++++++++++++- gdb/testsuite/gdb.threads/non-ldr-exc-2.c | 5 +++++ gdb/testsuite/gdb.threads/non-ldr-exc-2.exp | 26 +++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/gdb/testsuite/gdb.threads/leader-exit.c b/gdb/testsuite/gdb.th= reads/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 @@ =20 static volatile pthread_t main_thread; =20 +static volatile int wait_for_exit =3D 1; + static void * start (void *arg) { @@ -28,6 +30,8 @@ start (void *arg) =20 i =3D pthread_join (main_thread, NULL); assert (i =3D=3D 0); + while (wait_for_exit) + usleep (100 * 1000); =20 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..fb2f6980c2a 100644 --- a/gdb/testsuite/gdb.threads/leader-exit.exp +++ b/gdb/testsuite/gdb.threads/leader-exit.exp @@ -30,7 +30,29 @@ if {![runto_main]} { return } =20 -gdb_breakpoint [gdb_get_line_number "break-here"] +# 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 exit the wait_for_exit loop. +gdb_test_no_output "set var wait_for_exit =3D 0" + +gdb_breakpoint $srcfile:[gdb_get_line_number "break-here"] gdb_continue_to_breakpoint "break-here" ".* break-here .*" =20 gdb_test "info threads" \ 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 =3D "go away"; =20 +static volatile int wait_for_exit =3D 1; + static void * thread_execler (void *arg) { @@ -34,6 +36,9 @@ thread_execler (void *arg) i =3D pthread_join (main_thread, NULL); assert (i =3D=3D 0); =20 + while (wait_for_exit) + usleep (100 * 1000); + /* Exec ourselves again. */ if (execl (image, image, argv1, NULL) =3D=3D -1) /* break-here */ { diff --git a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp b/gdb/testsuite/gd= b.threads/non-ldr-exc-2.exp index ead262cc2b5..3f465e10159 100644 --- a/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp +++ b/gdb/testsuite/gdb.threads/non-ldr-exc-2.exp @@ -17,6 +17,8 @@ # through to the new incarnation of the main thread, even if the main # thread had already exited before the exec. =20 +require {!target_info exists gdb,nointerrupts} + standard_testfile set executable ${testfile} =20 @@ -37,7 +39,29 @@ proc do_test { lock_sched nonstop } { return -1 } =20 - gdb_breakpoint [gdb_get_line_number "break-here"] + # 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 exit the wait_for_exit loop. + gdb_test_no_output "set var wait_for_exit =3D 0" + + gdb_breakpoint $::srcfile:[gdb_get_line_number "break-here"] gdb_continue_to_breakpoint "break-here" ".* break-here .*" =20 if { $nonstop =3D=3D "on" } {