Files
binutils-gdb/gdb/testsuite/gdb.base/watch_thread_num.c
Tom de Vries 169a287181 [gdb/testsuite] Fix interrupted sleep in multi-threaded test-cases
When running test-case gdb.threads/continue-pending-status.exp with native, I
have:
...
(gdb) continue^M
Continuing.^M
PASS: gdb.threads/continue-pending-status.exp: attempt 0: continue for ctrl-c
^C^M
Thread 1 "continue-pendin" received signal SIGINT, Interrupt.^M
[Switching to Thread 0x7ffff7fc4740 (LWP 1276)]^M
0x00007ffff758e4c0 in __GI___nanosleep () at nanosleep.c:27^M
27        return SYSCALL_CANCEL (nanosleep, requested_time, remaining);^M
(gdb) PASS: gdb.threads/continue-pending-status.exp: attempt 0: caught interrupt
...
but with target board unix/-m32, I run into:
...
(gdb) continue^M
Continuing.^M
PASS: gdb.threads/continue-pending-status.exp: attempt 0: continue for ctrl-c
[Thread 0xf74aeb40 (LWP 31957) exited]^M
[Thread 0xf7cafb40 (LWP 31956) exited]^M
[Inferior 1 (process 31952) exited normally]^M
(gdb) Quit^M
...

The problem is that the sleep (300) call at the end of main is interrupted,
which causes the inferior to exit before the ctrl-c can be send.

This problem is described at "Interrupted System Calls" in the docs, and the
suggested solution (using a sleep loop) indeed fixes the problem.

Fix this instead using the more prevalent:
...
  alarm (300);
  ...
  while (1) sleep (1);
...
which is roughly equivalent because the sleep is called at the end of main,
but slightly better because it guards against hangs from the start rather than
from the end of main.

Likewise in gdb.base/watch_thread_num.exp.

Likewise in gdb.btrace/enable-running.exp, but use the sleep loop there,
because the sleep is not called at the end of main.

Tested on x86_64-linux.
2021-09-16 14:27:01 +02:00

100 lines
2.3 KiB
C

/* This testcase is part of GDB, the GNU debugger.
Copyright 2002-2021 Free Software Foundation, Inc.
Copyright 1992, 1993, 1994, 1995, 1999, 2002, 2003, 2007, 2008, 2009
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 file is copied from schedlock.c. */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function (void *arg); /* Pointer to function executed by each thread */
static pthread_barrier_t threads_started_barrier;
static pthread_barrier_t threads_started_barrier2;
#define NUM 15
static int num_threads = NUM;
static unsigned int shared_var = 1;
int main () {
int res;
pthread_t threads[NUM];
void *thread_result;
long i;
alarm (180);
pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1);
pthread_barrier_init (&threads_started_barrier2, NULL, 2);
for (i = 0; i < NUM; i++)
{
res = pthread_create (&threads[i],
NULL,
thread_function,
(void *) i);
}
pthread_barrier_wait (&threads_started_barrier);
pthread_barrier_wait (&threads_started_barrier2); /* all threads started */
pthread_join (threads[0], NULL);
/* first child thread exited */
while (1)
sleep (1);
exit (EXIT_SUCCESS);
}
void
loop (void)
{
}
void *thread_function (void *arg) {
int my_number = (long) arg;
pthread_barrier_wait (&threads_started_barrier);
if (my_number > 0)
{
/* Don't run forever. Run just short of it :) */
while (shared_var > 0)
{
shared_var++;
usleep (1); /* Loop increment. */
loop ();
}
}
else
pthread_barrier_wait (&threads_started_barrier2);
pthread_exit (NULL);
}