OLD | NEW |
1 /* This testcase is part of GDB, the GNU debugger. | 1 /* This testcase is part of GDB, the GNU debugger. |
2 | 2 |
3 Copyright 2009-2012 Free Software Foundation, Inc. | 3 Copyright 2010-2012 Free Software Foundation, Inc. |
4 | 4 |
5 This program is free software; you can redistribute it and/or modify | 5 This program is free software; you can redistribute it and/or modify |
6 it under the terms of the GNU General Public License as published by | 6 it under the terms of the GNU General Public License as published by |
7 the Free Software Foundation; either version 3 of the License, or | 7 the Free Software Foundation; either version 3 of the License, or |
8 (at your option) any later version. | 8 (at your option) any later version. |
9 | 9 |
10 This program is distributed in the hope that it will be useful, | 10 This program is distributed in the hope that it will be useful, |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 GNU General Public License for more details. | 13 GNU General Public License for more details. |
14 | 14 |
15 You should have received a copy of the GNU General Public License | 15 You should have received a copy of the GNU General Public License |
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
17 | 17 |
18 #define _GNU_SOURCE | 18 #define _GNU_SOURCE |
19 #include <pthread.h> | 19 #include <pthread.h> |
20 #include <stdio.h> | 20 #include <stdio.h> |
21 #include <limits.h> | 21 #include <limits.h> |
22 #include <errno.h> | 22 #include <errno.h> |
23 #include <stdlib.h> | 23 #include <stdlib.h> |
24 #include <string.h> | 24 #include <string.h> |
25 #include <assert.h> | 25 #include <assert.h> |
26 #include <sys/types.h> | 26 #include <sys/types.h> |
27 #include <signal.h> | 27 #include <signal.h> |
28 #include <unistd.h> | 28 #include <unistd.h> |
29 #include <asm/unistd.h> | 29 #include <asm/unistd.h> |
30 | 30 |
31 #define gettid() syscall (__NR_gettid) | 31 #define gettid() syscall (__NR_gettid) |
| 32 #define tgkill(tgid, tid, sig) syscall (__NR_tgkill, tgid, tid, sig) |
32 | 33 |
33 /* Terminate always in the main task, it can lock up with SIGSTOPped GDB | 34 /* Terminate always in the main task. It can lock up with SIGSTOPped |
34 otherwise. */ | 35 GDB otherwise. */ |
35 #define TIMEOUT (gettid () == getpid() ? 10 : 15) | 36 #define TIMEOUT (gettid () == getpid() ? 10 : 15) |
36 | 37 |
37 static pid_t thread1_tid; | 38 static pid_t thread1_tid; |
38 static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER; | 39 static pthread_cond_t thread1_tid_cond |
39 static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_
NP; | 40 = PTHREAD_COND_INITIALIZER; |
| 41 static pthread_mutex_t thread1_tid_mutex |
| 42 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
| 43 static int thread1_sigusr1_hit; |
| 44 static int thread1_sigusr2_hit; |
40 | 45 |
41 static pid_t thread2_tid; | 46 static pid_t thread2_tid; |
42 static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER; | 47 static pthread_cond_t thread2_tid_cond |
43 static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_
NP; | 48 = PTHREAD_COND_INITIALIZER; |
| 49 static pthread_mutex_t thread2_tid_mutex |
| 50 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
| 51 static int thread2_sigusr1_hit; |
| 52 static int thread2_sigusr2_hit; |
44 | 53 |
45 static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
; | 54 static pthread_mutex_t terminate_mutex |
| 55 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
46 | 56 |
47 /* These variables must have lower in-memory addresses than thread1_rwatch and | 57 /* Do not use alarm as it would create a ptrace event which would hang |
48 thread2_rwatch so that they take their watchpoint slots. */ | 58 us up if we are being traced by GDB, which we stopped |
| 59 ourselves. */ |
49 | 60 |
50 static int unused1_rwatch; | 61 static void |
51 static int unused2_rwatch; | 62 timed_mutex_lock (pthread_mutex_t *mutex) |
52 | |
53 static volatile int thread1_rwatch; | |
54 static volatile int thread2_rwatch; | |
55 | |
56 /* Do not use alarm as it would create a ptrace event which would hang up us if | |
57 we are being traced by GDB which we stopped ourselves. */ | |
58 | |
59 static void timed_mutex_lock (pthread_mutex_t *mutex) | |
60 { | 63 { |
61 int i; | 64 int i; |
62 struct timespec start, now; | 65 struct timespec start, now; |
63 | 66 |
64 i = clock_gettime (CLOCK_MONOTONIC, &start); | 67 i = clock_gettime (CLOCK_MONOTONIC, &start); |
65 assert (i == 0); | 68 assert (i == 0); |
66 | 69 |
67 do | 70 do |
68 { | 71 { |
69 i = pthread_mutex_trylock (mutex); | 72 i = pthread_mutex_trylock (mutex); |
70 if (i == 0) | 73 if (i == 0) |
71 return; | 74 return; |
72 assert (i == EBUSY); | 75 assert (i == EBUSY); |
73 | 76 |
74 i = clock_gettime (CLOCK_MONOTONIC, &now); | 77 i = clock_gettime (CLOCK_MONOTONIC, &now); |
75 assert (i == 0); | 78 assert (i == 0); |
76 assert (now.tv_sec >= start.tv_sec); | 79 assert (now.tv_sec >= start.tv_sec); |
77 } | 80 } |
78 while (now.tv_sec - start.tv_sec < TIMEOUT); | 81 while (now.tv_sec - start.tv_sec < TIMEOUT); |
79 | 82 |
80 fprintf (stderr, "Timed out waiting for internal lock!\n"); | 83 fprintf (stderr, "Timed out waiting for internal lock!\n"); |
81 exit (EXIT_FAILURE); | 84 exit (EXIT_FAILURE); |
82 } | 85 } |
83 | 86 |
| 87 static void |
| 88 handler (int signo, siginfo_t *siginfo, void *exception) |
| 89 { |
| 90 int *varp; |
| 91 |
| 92 assert (siginfo->si_signo == signo); |
| 93 assert (siginfo->si_code == SI_TKILL); |
| 94 assert (siginfo->si_pid == getpid ()); |
| 95 |
| 96 if (gettid () == thread1_tid) |
| 97 { |
| 98 if (signo == SIGUSR1) |
| 99 varp = &thread1_sigusr1_hit; |
| 100 else if (signo == SIGUSR2) |
| 101 varp = &thread1_sigusr2_hit; |
| 102 else |
| 103 assert (0); |
| 104 } |
| 105 else if (gettid () == thread2_tid) |
| 106 { |
| 107 if (signo == SIGUSR1) |
| 108 varp = &thread2_sigusr1_hit; |
| 109 else if (signo == SIGUSR2) |
| 110 varp = &thread2_sigusr2_hit; |
| 111 else |
| 112 assert (0); |
| 113 } |
| 114 else |
| 115 assert (0); |
| 116 |
| 117 if (*varp) |
| 118 { |
| 119 fprintf (stderr, "Signal %d for TID %lu has been already hit!\n", signo, |
| 120 (unsigned long) gettid ()); |
| 121 exit (EXIT_FAILURE); |
| 122 } |
| 123 *varp = 1; |
| 124 } |
| 125 |
84 static void * | 126 static void * |
85 thread1_func (void *unused) | 127 thread1_func (void *unused) |
86 { | 128 { |
87 int i; | 129 int i; |
88 volatile int rwatch_store; | |
89 | 130 |
90 timed_mutex_lock (&thread1_tid_mutex); | 131 timed_mutex_lock (&thread1_tid_mutex); |
91 | 132 |
92 /* THREAD1_TID_MUTEX must be already locked to avoid race. */ | 133 /* THREAD1_TID_MUTEX must be already locked to avoid a race. */ |
93 thread1_tid = gettid (); | 134 thread1_tid = gettid (); |
94 | 135 |
95 i = pthread_cond_signal (&thread1_tid_cond); | 136 i = pthread_cond_signal (&thread1_tid_cond); |
96 assert (i == 0); | 137 assert (i == 0); |
97 i = pthread_mutex_unlock (&thread1_tid_mutex); | 138 i = pthread_mutex_unlock (&thread1_tid_mutex); |
98 assert (i == 0); | 139 assert (i == 0); |
99 | 140 |
100 rwatch_store = thread1_rwatch; | 141 /* Be sure the "t (tracing stop)" test can proceed for both |
101 | 142 threads. */ |
102 /* Be sure the "t (tracing stop)" test can proceed for both threads. */ | |
103 timed_mutex_lock (&terminate_mutex); | 143 timed_mutex_lock (&terminate_mutex); |
104 i = pthread_mutex_unlock (&terminate_mutex); | 144 i = pthread_mutex_unlock (&terminate_mutex); |
105 assert (i == 0); | 145 assert (i == 0); |
106 | 146 |
| 147 if (!thread1_sigusr1_hit) |
| 148 { |
| 149 fprintf (stderr, "Thread 1 signal SIGUSR1 not hit!\n"); |
| 150 exit (EXIT_FAILURE); |
| 151 } |
| 152 if (!thread1_sigusr2_hit) |
| 153 { |
| 154 fprintf (stderr, "Thread 1 signal SIGUSR2 not hit!\n"); |
| 155 exit (EXIT_FAILURE); |
| 156 } |
| 157 |
107 return NULL; | 158 return NULL; |
108 } | 159 } |
109 | 160 |
110 static void * | 161 static void * |
111 thread2_func (void *unused) | 162 thread2_func (void *unused) |
112 { | 163 { |
113 int i; | 164 int i; |
114 volatile int rwatch_store; | |
115 | 165 |
116 timed_mutex_lock (&thread2_tid_mutex); | 166 timed_mutex_lock (&thread2_tid_mutex); |
117 | 167 |
118 /* THREAD2_TID_MUTEX must be already locked to avoid race. */ | 168 /* THREAD2_TID_MUTEX must be already locked to avoid a race. */ |
119 thread2_tid = gettid (); | 169 thread2_tid = gettid (); |
120 | 170 |
121 i = pthread_cond_signal (&thread2_tid_cond); | 171 i = pthread_cond_signal (&thread2_tid_cond); |
122 assert (i == 0); | 172 assert (i == 0); |
123 i = pthread_mutex_unlock (&thread2_tid_mutex); | 173 i = pthread_mutex_unlock (&thread2_tid_mutex); |
124 assert (i == 0); | 174 assert (i == 0); |
125 | 175 |
126 rwatch_store = thread2_rwatch; | 176 /* Be sure the "t (tracing stop)" test can proceed for both |
127 | 177 threads. */ |
128 /* Be sure the "t (tracing stop)" test can proceed for both threads. */ | |
129 timed_mutex_lock (&terminate_mutex); | 178 timed_mutex_lock (&terminate_mutex); |
130 i = pthread_mutex_unlock (&terminate_mutex); | 179 i = pthread_mutex_unlock (&terminate_mutex); |
131 assert (i == 0); | 180 assert (i == 0); |
132 | 181 |
| 182 if (!thread2_sigusr1_hit) |
| 183 { |
| 184 fprintf (stderr, "Thread 2 signal SIGUSR1 not hit!\n"); |
| 185 exit (EXIT_FAILURE); |
| 186 } |
| 187 if (!thread2_sigusr2_hit) |
| 188 { |
| 189 fprintf (stderr, "Thread 2 signal SIGUSR2 not hit!\n"); |
| 190 exit (EXIT_FAILURE); |
| 191 } |
| 192 |
133 return NULL; | 193 return NULL; |
134 } | 194 } |
135 | 195 |
136 static const char * | 196 static const char * |
137 proc_string (const char *filename, const char *line) | 197 proc_string (const char *filename, const char *line) |
138 { | 198 { |
139 FILE *f; | 199 FILE *f; |
140 static char buf[LINE_MAX]; | 200 static char buf[LINE_MAX]; |
141 size_t line_len = strlen (line); | 201 size_t line_len = strlen (line); |
142 | 202 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 i = kill (tracer_save, SIGCONT); | 319 i = kill (tracer_save, SIGCONT); |
260 assert (i == 0); | 320 assert (i == 0); |
261 } | 321 } |
262 } | 322 } |
263 | 323 |
264 int | 324 int |
265 main (int argc, char **argv) | 325 main (int argc, char **argv) |
266 { | 326 { |
267 int i; | 327 int i; |
268 int standalone = 0; | 328 int standalone = 0; |
| 329 struct sigaction act; |
269 | 330 |
270 if (argc == 2 && strcmp (argv[1], "-s") == 0) | 331 if (argc == 2 && strcmp (argv[1], "-s") == 0) |
271 standalone = 1; | 332 standalone = 1; |
272 else | 333 else |
273 assert (argc == 1); | 334 assert (argc == 1); |
274 | 335 |
275 setbuf (stdout, NULL); | 336 setbuf (stdout, NULL); |
276 | 337 |
277 timed_mutex_lock (&thread1_tid_mutex); | 338 timed_mutex_lock (&thread1_tid_mutex); |
278 timed_mutex_lock (&thread2_tid_mutex); | 339 timed_mutex_lock (&thread2_tid_mutex); |
279 | 340 |
280 timed_mutex_lock (&terminate_mutex); | 341 timed_mutex_lock (&terminate_mutex); |
281 | 342 |
| 343 errno = 0; |
| 344 memset (&act, 0, sizeof (act)); |
| 345 act.sa_sigaction = handler; |
| 346 act.sa_flags = SA_RESTART | SA_SIGINFO; |
| 347 i = sigemptyset (&act.sa_mask); |
| 348 assert_perror (errno); |
| 349 assert (i == 0); |
| 350 i = sigaction (SIGUSR1, &act, NULL); |
| 351 assert_perror (errno); |
| 352 assert (i == 0); |
| 353 i = sigaction (SIGUSR2, &act, NULL); |
| 354 assert_perror (errno); |
| 355 assert (i == 0); |
| 356 |
282 i = pthread_create (&thread1, NULL, thread1_func, NULL); | 357 i = pthread_create (&thread1, NULL, thread1_func, NULL); |
283 assert (i == 0); | 358 assert (i == 0); |
284 | 359 |
285 i = pthread_create (&thread2, NULL, thread2_func, NULL); | 360 i = pthread_create (&thread2, NULL, thread2_func, NULL); |
286 assert (i == 0); | 361 assert (i == 0); |
287 | 362 |
288 if (!standalone) | 363 if (!standalone) |
289 { | 364 { |
290 tracer = proc_ulong ("/proc/self/status", "TracerPid:\t"); | 365 tracer = proc_ulong ("/proc/self/status", "TracerPid:\t"); |
291 if (tracer == 0) | 366 if (tracer == 0) |
(...skipping 15 matching lines...) Expand all Loading... |
307 | 382 |
308 printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); | 383 printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer); |
309 | 384 |
310 if (tracer) | 385 if (tracer) |
311 { | 386 { |
312 i = kill (tracer, SIGSTOP); | 387 i = kill (tracer, SIGSTOP); |
313 assert (i == 0); | 388 assert (i == 0); |
314 state_wait (tracer, "T (stopped)"); | 389 state_wait (tracer, "T (stopped)"); |
315 } | 390 } |
316 | 391 |
317 /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) and so | 392 /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex) |
318 they could not trigger the watchpoints before GDB gets unstopped later. | 393 and so they could not trigger the signals before GDB is unstopped |
319 Threads get resumed at pthread_cond_wait below. Use `while' loops for | 394 later. Threads get resumed by the pthread_cond_wait below. Use |
320 protection against spurious pthread_cond_wait wakeups. */ | 395 `while' loops for protection against spurious pthread_cond_wait |
| 396 wakeups. */ |
321 | 397 |
322 printf ("Waiting till the threads initialize their TIDs.\n"); | 398 printf ("Waiting till the threads initialize their TIDs.\n"); |
323 | 399 |
324 while (thread1_tid == 0) | 400 while (thread1_tid == 0) |
325 { | 401 { |
326 i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex); | 402 i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex); |
327 assert (i == 0); | 403 assert (i == 0); |
328 } | 404 } |
329 | 405 |
330 while (thread2_tid == 0) | 406 while (thread2_tid == 0) |
331 { | 407 { |
332 i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex); | 408 i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex); |
333 assert (i == 0); | 409 assert (i == 0); |
334 } | 410 } |
335 | 411 |
336 printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n", | 412 printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n", |
337 (unsigned long) thread1_tid, (unsigned long) thread2_tid, | 413 (unsigned long) thread1_tid, (unsigned long) thread2_tid, |
338 (unsigned long) getpid ()); | 414 (unsigned long) getpid ()); |
339 | 415 |
340 printf ("Waiting till the threads get trapped by the watchpoints.\n"); | 416 errno = 0; |
| 417 i = tgkill (getpid (), thread1_tid, SIGUSR1); |
| 418 assert_perror (errno); |
| 419 assert (i == 0); |
| 420 i = tgkill (getpid (), thread1_tid, SIGUSR2); |
| 421 assert_perror (errno); |
| 422 assert (i == 0); |
| 423 i = tgkill (getpid (), thread2_tid, SIGUSR1); |
| 424 assert_perror (errno); |
| 425 assert (i == 0); |
| 426 i = tgkill (getpid (), thread2_tid, SIGUSR2); |
| 427 assert_perror (errno); |
| 428 assert (i == 0); |
| 429 |
| 430 printf ("Waiting till the threads are trapped by the signals.\n"); |
341 | 431 |
342 if (tracer) | 432 if (tracer) |
343 { | 433 { |
344 /* s390x-unknown-linux-gnu will fail with "R (running)". */ | 434 /* s390x-unknown-linux-gnu will fail with "R (running)". */ |
345 | 435 |
346 state_wait (thread1_tid, "t (tracing stop)"); | 436 state_wait (thread1_tid, "t (tracing stop)"); |
347 | 437 |
348 state_wait (thread2_tid, "t (tracing stop)"); | 438 state_wait (thread2_tid, "t (tracing stop)"); |
349 } | 439 } |
350 | 440 |
351 cleanup (); | 441 cleanup (); |
352 | 442 |
353 printf ("Joining the threads.\n"); | 443 printf ("Joining the threads.\n"); |
354 | 444 |
355 i = pthread_mutex_unlock (&terminate_mutex); | 445 i = pthread_mutex_unlock (&terminate_mutex); |
356 assert (i == 0); | 446 assert (i == 0); |
357 | 447 |
358 i = pthread_join (thread1, NULL); | 448 i = pthread_join (thread1, NULL); |
359 assert (i == 0); | 449 assert (i == 0); |
360 | 450 |
361 i = pthread_join (thread2, NULL); | 451 i = pthread_join (thread2, NULL); |
362 assert (i == 0); | 452 assert (i == 0); |
363 | 453 |
364 printf ("Exiting.\n"); /* break-at-exit */ | 454 printf ("Exiting.\n"); /* break-at-exit */ |
365 | 455 |
366 /* Just prevent compiler `warning: unusedX_rwatch defined but not used'. */ | |
367 unused1_rwatch = 1; | |
368 unused2_rwatch = 2; | |
369 | |
370 return EXIT_SUCCESS; | 456 return EXIT_SUCCESS; |
371 } | 457 } |
OLD | NEW |