1 /* This testcase is part of GDB, the GNU debugger.
3 Copyright 2010-2024 Free Software Foundation, Inc.
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
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
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/>. */
26 #include <sys/types.h>
29 #include <asm/unistd.h>
31 #define gettid() syscall (__NR_gettid)
32 #define tgkill(tgid, tid, sig) syscall (__NR_tgkill, tgid, tid, sig)
34 /* Terminate always in the main task. It can lock up with SIGSTOPped
36 #define TIMEOUT (gettid () == getpid() ? 10 : 15)
38 static pid_t thread1_tid
;
39 static pthread_cond_t thread1_tid_cond
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
;
46 static pid_t thread2_tid
;
47 static pthread_cond_t thread2_tid_cond
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
;
54 static pthread_mutex_t terminate_mutex
55 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
;
57 static pthread_barrier_t threads_started_barrier
;
59 /* Do not use alarm as it would create a ptrace event which would hang
60 us up if we are being traced by GDB, which we stopped
64 timed_mutex_lock (pthread_mutex_t
*mutex
)
67 struct timespec start
, now
;
69 i
= clock_gettime (CLOCK_MONOTONIC
, &start
);
74 i
= pthread_mutex_trylock (mutex
);
79 i
= clock_gettime (CLOCK_MONOTONIC
, &now
);
81 assert (now
.tv_sec
>= start
.tv_sec
);
83 while (now
.tv_sec
- start
.tv_sec
< TIMEOUT
);
85 fprintf (stderr
, "Timed out waiting for internal lock!\n");
90 handler (int signo
, siginfo_t
*siginfo
, void *exception
)
94 assert (siginfo
->si_signo
== signo
);
95 assert (siginfo
->si_code
== SI_TKILL
);
96 assert (siginfo
->si_pid
== getpid ());
98 if (gettid () == thread1_tid
)
100 if (signo
== SIGUSR1
)
101 varp
= &thread1_sigusr1_hit
;
102 else if (signo
== SIGUSR2
)
103 varp
= &thread1_sigusr2_hit
;
107 else if (gettid () == thread2_tid
)
109 if (signo
== SIGUSR1
)
110 varp
= &thread2_sigusr1_hit
;
111 else if (signo
== SIGUSR2
)
112 varp
= &thread2_sigusr2_hit
;
121 fprintf (stderr
, "Signal %d for TID %lu has been already hit!\n", signo
,
122 (unsigned long) gettid ());
129 thread1_func (void *unused
)
133 pthread_barrier_wait (&threads_started_barrier
);
135 timed_mutex_lock (&thread1_tid_mutex
);
137 /* THREAD1_TID_MUTEX must be already locked to avoid a race. */
138 thread1_tid
= gettid ();
140 i
= pthread_cond_signal (&thread1_tid_cond
);
142 i
= pthread_mutex_unlock (&thread1_tid_mutex
);
145 /* Be sure the "t (tracing stop)" test can proceed for both
147 timed_mutex_lock (&terminate_mutex
);
148 i
= pthread_mutex_unlock (&terminate_mutex
);
151 if (!thread1_sigusr1_hit
)
153 fprintf (stderr
, "Thread 1 signal SIGUSR1 not hit!\n");
156 if (!thread1_sigusr2_hit
)
158 fprintf (stderr
, "Thread 1 signal SIGUSR2 not hit!\n");
166 thread2_func (void *unused
)
170 pthread_barrier_wait (&threads_started_barrier
);
172 timed_mutex_lock (&thread2_tid_mutex
);
174 /* THREAD2_TID_MUTEX must be already locked to avoid a race. */
175 thread2_tid
= gettid ();
177 i
= pthread_cond_signal (&thread2_tid_cond
);
179 i
= pthread_mutex_unlock (&thread2_tid_mutex
);
182 /* Be sure the "t (tracing stop)" test can proceed for both
184 timed_mutex_lock (&terminate_mutex
);
185 i
= pthread_mutex_unlock (&terminate_mutex
);
188 if (!thread2_sigusr1_hit
)
190 fprintf (stderr
, "Thread 2 signal SIGUSR1 not hit!\n");
193 if (!thread2_sigusr2_hit
)
195 fprintf (stderr
, "Thread 2 signal SIGUSR2 not hit!\n");
203 proc_string (const char *filename
, const char *line
)
206 static char buf
[LINE_MAX
];
207 size_t line_len
= strlen (line
);
209 f
= fopen (filename
, "r");
212 fprintf (stderr
, "fopen (\"%s\") for \"%s\": %s\n", filename
, line
,
216 while (errno
= 0, fgets (buf
, sizeof (buf
), f
))
220 s
= strchr (buf
, '\n');
224 if (strncmp (buf
, line
, line_len
) != 0)
229 fprintf (stderr
, "fclose (\"%s\") for \"%s\": %s\n", filename
, line
,
234 return &buf
[line_len
];
238 fprintf (stderr
, "fgets (\"%s\": %s\n", filename
, strerror (errno
));
241 fprintf (stderr
, "\"%s\": No line \"%s\" found.\n", filename
, line
);
246 proc_ulong (const char *filename
, const char *line
)
248 const char *s
= proc_string (filename
, line
);
253 retval
= strtol (s
, &end
, 10);
254 if (retval
< 0 || retval
>= LONG_MAX
|| (end
&& *end
))
256 fprintf (stderr
, "\"%s\":\"%s\": %ld, %s\n", filename
, line
, retval
,
264 state_wait (pid_t process
, const char *wanted
)
268 struct timespec start
, now
;
271 i
= asprintf (&filename
, "/proc/%lu/status", (unsigned long) process
);
274 i
= clock_gettime (CLOCK_MONOTONIC
, &start
);
279 state
= proc_string (filename
, "State:\t");
281 /* torvalds/linux-2.6.git 464763cf1c6df632dccc8f2f4c7e50163154a2c0
282 has changed "T (tracing stop)" to "t (tracing stop)". Make the GDB
283 testcase backward compatible with older Linux kernels. */
284 if (strcmp (state
, "T (tracing stop)") == 0)
285 state
= "t (tracing stop)";
287 if (strcmp (state
, wanted
) == 0)
295 perror ("sched_yield()");
299 i
= clock_gettime (CLOCK_MONOTONIC
, &now
);
301 assert (now
.tv_sec
>= start
.tv_sec
);
303 while (now
.tv_sec
- start
.tv_sec
< TIMEOUT
);
305 fprintf (stderr
, "Timed out waiting for PID %lu \"%s\" (now it is \"%s\")!\n",
306 (unsigned long) process
, wanted
, state
);
310 static volatile pid_t tracer
= 0;
311 static pthread_t thread1
, thread2
;
316 printf ("Resuming GDB PID %lu.\n", (unsigned long) tracer
);
321 int tracer_save
= tracer
;
325 i
= kill (tracer_save
, SIGCONT
);
331 main (int argc
, char **argv
)
335 struct sigaction act
;
337 if (argc
== 2 && strcmp (argv
[1], "-s") == 0)
342 setbuf (stdout
, NULL
);
344 timed_mutex_lock (&thread1_tid_mutex
);
345 timed_mutex_lock (&thread2_tid_mutex
);
347 timed_mutex_lock (&terminate_mutex
);
350 memset (&act
, 0, sizeof (act
));
351 act
.sa_sigaction
= handler
;
352 act
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
353 i
= sigemptyset (&act
.sa_mask
);
354 assert_perror (errno
);
356 i
= sigaction (SIGUSR1
, &act
, NULL
);
357 assert_perror (errno
);
359 i
= sigaction (SIGUSR2
, &act
, NULL
);
360 assert_perror (errno
);
363 pthread_barrier_init (&threads_started_barrier
, NULL
, 3);
365 i
= pthread_create (&thread1
, NULL
, thread1_func
, NULL
);
368 i
= pthread_create (&thread2
, NULL
, thread2_func
, NULL
);
373 tracer
= proc_ulong ("/proc/self/status", "TracerPid:\t");
376 fprintf (stderr
, "The testcase must be run by GDB!\n");
379 if (tracer
!= getppid ())
381 fprintf (stderr
, "The testcase parent must be our GDB tracer!\n");
386 /* SIGCONT our debugger in the case of our crash as we would deadlock
391 /* Wait until all threads are seen running. On Linux (at least),
392 new threads start stopped, and the debugger must resume them.
393 Need to wait for that before stopping GDB. */
394 pthread_barrier_wait (&threads_started_barrier
);
396 printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer
);
400 i
= kill (tracer
, SIGSTOP
);
402 state_wait (tracer
, "T (stopped)");
405 /* Threads are now waiting at timed_mutex_lock (thread1_tid_mutex)
406 and so they could not trigger the signals before GDB is unstopped
407 later. Threads get resumed by the pthread_cond_wait below. Use
408 `while' loops for protection against spurious pthread_cond_wait
411 printf ("Waiting till the threads initialize their TIDs.\n");
413 while (thread1_tid
== 0)
415 i
= pthread_cond_wait (&thread1_tid_cond
, &thread1_tid_mutex
);
419 while (thread2_tid
== 0)
421 i
= pthread_cond_wait (&thread2_tid_cond
, &thread2_tid_mutex
);
425 printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n",
426 (unsigned long) thread1_tid
, (unsigned long) thread2_tid
,
427 (unsigned long) getpid ());
430 i
= tgkill (getpid (), thread1_tid
, SIGUSR1
);
431 assert_perror (errno
);
433 i
= tgkill (getpid (), thread1_tid
, SIGUSR2
);
434 assert_perror (errno
);
436 i
= tgkill (getpid (), thread2_tid
, SIGUSR1
);
437 assert_perror (errno
);
439 i
= tgkill (getpid (), thread2_tid
, SIGUSR2
);
440 assert_perror (errno
);
443 printf ("Waiting till the threads are trapped by the signals.\n");
447 /* s390x-unknown-linux-gnu will fail with "R (running)". */
449 state_wait (thread1_tid
, "t (tracing stop)");
451 state_wait (thread2_tid
, "t (tracing stop)");
456 printf ("Joining the threads.\n");
458 i
= pthread_mutex_unlock (&terminate_mutex
);
461 i
= pthread_join (thread1
, NULL
);
464 i
= pthread_join (thread2
, NULL
);
467 printf ("Exiting.\n"); /* break-at-exit */