binutils-gdb/gdb/testsuite/gdb.threads/clone-new-thread-event.exp
Pedro Alves cdff184f42 Fix gdb.threads/clone-new-thread-event.exp race
If we make GDB report the process EXIT event for the leader thread,
instead of whatever is the last thread in the LWP list, as will be
done in a latter patch of this series, then
gdb.threads/current-lwp-dead.exp starts failing:

 (gdb) FAIL: gdb.threads/clone-new-thread-event.exp: catch SIGUSR1 (the program exited)

This is a testcase race -- the main thread does not wait for the
spawned clone "thread" to finish before exiting, so the main program
may exit before the second thread is scheduled and reports its
SIGUSR1.  With the change to make GDB report the EXIT for the leader,
the race is 100% reproducible by adding a sleep(), like so:

 --- c/gdb/testsuite/gdb.threads/clone-new-thread-event.c
 +++ w/gdb/testsuite/gdb.threads/clone-new-thread-event.c
 @@ -51,6 +51,7 @@ local_gettid (void)
  static int
  fn (void *unused)
  {
 +  sleep (1);
    tkill (local_gettid (), SIGUSR1);
    return 0;
  }

Resulting in:

 Breakpoint 1, main (argc=1, argv=0x7fffffffd418) at gdb.threads/clone-new-thread-event.c:65
 65        stack = malloc (STACK_SIZE);
 (gdb) continue
 Continuing.
 [New LWP 3715562]
 [Inferior 1 (process 3715555) exited normally]
 (gdb) FAIL: gdb.threads/clone-new-thread-event.exp: catch SIGUSR1 (the program exited)

That inferior exit reported is actually correct.  The main thread has
indeed exited, and that's the thread that has the right exit code to
report to the user, as that's the exit code that is reported to the
program's parent.  In this case, GDB managed to collect the exit code
for the leader thread before reaping the other thread, because in
reality, the testcase isn't creating standard threads, it is using raw
clone, and the new clones are put in their own thread group.

Fix it by making the main thread wait for the child to exit.  Also,
run the program to completion for completeness.

Change-Id: I315cd3dc2b9e860395dcab9658341ea868d7a6bf
2022-03-10 11:35:53 +00:00

36 lines
1.1 KiB
Plaintext

# This testcase is part of GDB, the GNU debugger.
# Copyright 2012-2022 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This only works on targets with the Linux kernel.
if ![istarget *-*-linux*] then {
return
}
if { [prepare_for_testing "failed to prepare" clone-new-thread-event] } {
return -1
}
if { ![runto_main] } {
return -1
}
gdb_test "continue" \
"Thread 2 received signal SIGUSR1, User defined signal 1.*" \
"catch SIGUSR1"
gdb_continue_to_end "" continue 1