Index: gdb/testsuite/gdb.threads/siginfo-threads.c |
diff --git a/gdb/testsuite/gdb.threads/watchthreads-reorder.c b/gdb/testsuite/gdb.threads/siginfo-threads.c |
similarity index 67% |
copy from gdb/testsuite/gdb.threads/watchthreads-reorder.c |
copy to gdb/testsuite/gdb.threads/siginfo-threads.c |
index ccded9920dd65607268e91cbf328ed7c50ef6db2..58590888ade00e88652d2ffb9c32cf6f8f6ee975 100644 |
--- a/gdb/testsuite/gdb.threads/watchthreads-reorder.c |
+++ b/gdb/testsuite/gdb.threads/siginfo-threads.c |
@@ -1,6 +1,6 @@ |
/* This testcase is part of GDB, the GNU debugger. |
- Copyright 2009-2012 Free Software Foundation, Inc. |
+ Copyright 2010-2012 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 |
@@ -29,34 +29,37 @@ |
#include <asm/unistd.h> |
#define gettid() syscall (__NR_gettid) |
+#define tgkill(tgid, tid, sig) syscall (__NR_tgkill, tgid, tid, sig) |
-/* Terminate always in the main task, it can lock up with SIGSTOPped GDB |
- otherwise. */ |
+/* Terminate always in the main task. It can lock up with SIGSTOPped |
+ GDB otherwise. */ |
#define TIMEOUT (gettid () == getpid() ? 10 : 15) |
static pid_t thread1_tid; |
-static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER; |
-static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
+static pthread_cond_t thread1_tid_cond |
+ = PTHREAD_COND_INITIALIZER; |
+static pthread_mutex_t thread1_tid_mutex |
+ = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
+static int thread1_sigusr1_hit; |
+static int thread1_sigusr2_hit; |
static pid_t thread2_tid; |
-static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER; |
-static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
+static pthread_cond_t thread2_tid_cond |
+ = PTHREAD_COND_INITIALIZER; |
+static pthread_mutex_t thread2_tid_mutex |
+ = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
+static int thread2_sigusr1_hit; |
+static int thread2_sigusr2_hit; |
-static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
+static pthread_mutex_t terminate_mutex |
+ = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
-/* These variables must have lower in-memory addresses than thread1_rwatch and |
- thread2_rwatch so that they take their watchpoint slots. */ |
+/* Do not use alarm as it would create a ptrace event which would hang |
+ us up if we are being traced by GDB, which we stopped |
+ ourselves. */ |
-static int unused1_rwatch; |
-static int unused2_rwatch; |
- |
-static volatile int thread1_rwatch; |
-static volatile int thread2_rwatch; |
- |
-/* Do not use alarm as it would create a ptrace event which would hang up us if |
- we are being traced by GDB which we stopped ourselves. */ |
- |
-static void timed_mutex_lock (pthread_mutex_t *mutex) |
+static void |
+timed_mutex_lock (pthread_mutex_t *mutex) |
{ |
int i; |
struct timespec start, now; |
@@ -81,15 +84,53 @@ static void timed_mutex_lock (pthread_mutex_t *mutex) |
exit (EXIT_FAILURE); |
} |
+static void |
+handler (int signo, siginfo_t *siginfo, void *exception) |
+{ |
+ int *varp; |
+ |
+ assert (siginfo->si_signo == signo); |
+ assert (siginfo->si_code == SI_TKILL); |
+ assert (siginfo->si_pid == getpid ()); |
+ |
+ if (gettid () == thread1_tid) |
+ { |
+ if (signo == SIGUSR1) |
+ varp = &thread1_sigusr1_hit; |
+ else if (signo == SIGUSR2) |
+ varp = &thread1_sigusr2_hit; |
+ else |
+ assert (0); |
+ } |
+ else if (gettid () == thread2_tid) |
+ { |
+ if (signo == SIGUSR1) |
+ varp = &thread2_sigusr1_hit; |
+ else if (signo == SIGUSR2) |
+ varp = &thread2_sigusr2_hit; |
+ else |
+ assert (0); |
+ } |
+ else |
+ assert (0); |
+ |
+ if (*varp) |
+ { |
+ fprintf (stderr, "Signal %d for TID %lu has been already hit!\n", signo, |
+ (unsigned long) gettid ()); |
+ exit (EXIT_FAILURE); |
+ } |
+ *varp = 1; |
+} |
+ |
static void * |
thread1_func (void *unused) |
{ |
int i; |
- volatile int rwatch_store; |
timed_mutex_lock (&thread1_tid_mutex); |
- /* THREAD1_TID_MUTEX must be already locked to avoid race. */ |
+ /* THREAD1_TID_MUTEX must be already locked to avoid a race. */ |
thread1_tid = gettid (); |
i = pthread_cond_signal (&thread1_tid_cond); |
@@ -97,13 +138,23 @@ thread1_func (void *unused) |
i = pthread_mutex_unlock (&thread1_tid_mutex); |
assert (i == 0); |
- rwatch_store = thread1_rwatch; |
- |
- /* Be sure the "t (tracing stop)" test can proceed for both threads. */ |
+ /* Be sure the "t (tracing stop)" test can proceed for both |
+ threads. */ |
timed_mutex_lock (&terminate_mutex); |
i = pthread_mutex_unlock (&terminate_mutex); |
assert (i == 0); |
+ if (!thread1_sigusr1_hit) |
+ { |
+ fprintf (stderr, "Thread 1 signal SIGUSR1 not hit!\n"); |
+ exit (EXIT_FAILURE); |
+ } |
+ if (!thread1_sigusr2_hit) |
+ { |
+ fprintf (stderr, "Thread 1 signal SIGUSR2 not hit!\n"); |
+ exit (EXIT_FAILURE); |
+ } |
+ |
return NULL; |
} |
@@ -111,11 +162,10 @@ static void * |
thread2_func (void *unused) |
{ |
int i; |
- volatile int rwatch_store; |
timed_mutex_lock (&thread2_tid_mutex); |
- /* THREAD2_TID_MUTEX must be already locked to avoid race. */ |
+ /* THREAD2_TID_MUTEX must be already locked to avoid a race. */ |
thread2_tid = gettid (); |
i = pthread_cond_signal (&thread2_tid_cond); |
@@ -123,13 +173,23 @@ thread2_func (void *unused) |
i = pthread_mutex_unlock (&thread2_tid_mutex); |
assert (i == 0); |
- rwatch_store = thread2_rwatch; |
- |
- /* Be sure the "t (tracing stop)" test can proceed for both threads. */ |
+ /* Be sure the "t (tracing stop)" test can proceed for both |
+ threads. */ |
timed_mutex_lock (&terminate_mutex); |
i = pthread_mutex_unlock (&terminate_mutex); |
assert (i == 0); |
+ if (!thread2_sigusr1_hit) |
+ { |
+ fprintf (stderr, "Thread 2 signal SIGUSR1 not hit!\n"); |
+ exit (EXIT_FAILURE); |
+ } |
+ if (!thread2_sigusr2_hit) |
+ { |
+ fprintf (stderr, "Thread 2 signal SIGUSR2 not hit!\n"); |
+ exit (EXIT_FAILURE); |
+ } |
+ |
return NULL; |
} |
@@ -266,6 +326,7 @@ main (int argc, char **argv) |
{ |
int i; |
int standalone = 0; |
+ struct sigaction act; |
if (argc == 2 && strcmp (argv[1], "-s") == 0) |
standalone = 1; |
@@ -279,6 +340,20 @@ main (int argc, char **argv) |
timed_mutex_lock (&terminate_mutex); |
+ errno = 0; |
+ memset (&act, 0, sizeof (act)); |
+ act.sa_sigaction = handler; |
+ act.sa_flags = SA_RESTART | SA_SIGINFO; |
+ i = sigemptyset (&act.sa_mask); |
+ assert_perror (errno); |
+ assert (i == 0); |
+ i = sigaction (SIGUSR1, &act, NULL); |
+ assert_perror (errno); |
+ assert (i == 0); |
+ i = sigaction (SIGUSR2, &act, NULL); |
+ assert_perror (errno); |
+ assert (i == 0); |
+ |
i = pthread_create (&thread1, NULL, thread1_func, NULL); |
assert (i == 0); |
@@ -314,10 +389,11 @@ main (int argc, char **argv) |
state_wait (tracer, "T (stopped)"); |
} |
- /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so |
- they could not trigger the watchpoints before GDB gets unstopped later. |
- Threads get resumed at pthread_cond_wait below. Use `while' loops for |
- protection against spurious pthread_cond_wait wakeups. */ |
+ /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) |
+ and so they could not trigger the signals before GDB is unstopped |
+ later. Threads get resumed by the pthread_cond_wait below. Use |
+ `while' loops for protection against spurious pthread_cond_wait |
+ wakeups. */ |
printf ("Waiting till the threads initialize their TIDs.\n"); |
@@ -337,7 +413,21 @@ main (int argc, char **argv) |
(unsigned long) thread1_tid, (unsigned long) thread2_tid, |
(unsigned long) getpid ()); |
- printf ("Waiting till the threads get trapped by the watchpoints.\n"); |
+ errno = 0; |
+ i = tgkill (getpid (), thread1_tid, SIGUSR1); |
+ assert_perror (errno); |
+ assert (i == 0); |
+ i = tgkill (getpid (), thread1_tid, SIGUSR2); |
+ assert_perror (errno); |
+ assert (i == 0); |
+ i = tgkill (getpid (), thread2_tid, SIGUSR1); |
+ assert_perror (errno); |
+ assert (i == 0); |
+ i = tgkill (getpid (), thread2_tid, SIGUSR2); |
+ assert_perror (errno); |
+ assert (i == 0); |
+ |
+ printf ("Waiting till the threads are trapped by the signals.\n"); |
if (tracer) |
{ |
@@ -363,9 +453,5 @@ main (int argc, char **argv) |
printf ("Exiting.\n"); /* break-at-exit */ |
- /* Just prevent compiler `warning: unusedX_rwatch defined but not used'. */ |
- unused1_rwatch = 1; |
- unused2_rwatch = 2; |
- |
return EXIT_SUCCESS; |
} |