t_ptrace_threads_wait.h revision 1.2 1 /* $NetBSD: t_ptrace_threads_wait.h,v 1.2 2025/05/02 02:24:32 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2016, 2017, 2018, 2019, 2020 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #define TRACE_THREADS_NUM 100
30
31 static volatile int done;
32 pthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER;
33
34 static void *
35 trace_threads_cb(void *arg __unused)
36 {
37
38 pthread_mutex_lock(&trace_threads_mtx);
39 done++;
40 pthread_mutex_unlock(&trace_threads_mtx);
41
42 while (done < TRACE_THREADS_NUM)
43 sched_yield();
44
45 return NULL;
46 }
47
48 static void
49 trace_threads(bool trace_create, bool trace_exit, bool masked)
50 {
51 const int sigval = SIGSTOP;
52 pid_t child, wpid;
53 #if defined(TWAIT_HAVE_STATUS)
54 int status;
55 #endif
56 ptrace_state_t state;
57 const int slen = sizeof(state);
58 ptrace_event_t event;
59 const int elen = sizeof(event);
60 struct ptrace_siginfo info;
61
62 sigset_t intmask;
63
64 pthread_t t[TRACE_THREADS_NUM];
65 int rv;
66 size_t n;
67 lwpid_t lid;
68
69 /* Track created and exited threads */
70 struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}};
71
72 DPRINTF("Before forking process PID=%d\n", getpid());
73 SYSCALL_REQUIRE((child = fork()) != -1);
74 if (child == 0) {
75 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
76 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
77
78 if (masked) {
79 sigemptyset(&intmask);
80 sigaddset(&intmask, SIGTRAP);
81 sigprocmask(SIG_BLOCK, &intmask, NULL);
82 }
83
84 DPRINTF("Before raising %s from child\n", strsignal(sigval));
85 FORKEE_ASSERT(raise(sigval) == 0);
86
87 for (n = 0; n < __arraycount(t); n++) {
88 rv = pthread_create(&t[n], NULL, trace_threads_cb,
89 NULL);
90 FORKEE_ASSERT(rv == 0);
91 }
92
93 for (n = 0; n < __arraycount(t); n++) {
94 rv = pthread_join(t[n], NULL);
95 FORKEE_ASSERT(rv == 0);
96 }
97
98 /*
99 * There is race between _exit() and pthread_join() detaching
100 * a thread. For simplicity kill the process after detecting
101 * LWP events.
102 */
103 while (true)
104 continue;
105
106 FORKEE_ASSERT(0 && "Not reached");
107 }
108 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
109
110 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
111 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
112
113 validate_status_stopped(status, sigval);
114
115 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
116 SYSCALL_REQUIRE(
117 ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
118
119 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
120 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
121 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
122 info.psi_siginfo.si_errno);
123
124 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
125 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
126
127 DPRINTF("Set LWP event mask for the child %d\n", child);
128 memset(&event, 0, sizeof(event));
129 if (trace_create)
130 event.pe_set_event |= PTRACE_LWP_CREATE;
131 if (trace_exit)
132 event.pe_set_event |= PTRACE_LWP_EXIT;
133 SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
134
135 DPRINTF("Before resuming the child process where it left off and "
136 "without signal to be sent\n");
137 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
138
139 for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
140 DPRINTF("Before calling %s() for the child - expected stopped "
141 "SIGTRAP\n", TWAIT_FNAME);
142 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
143 child);
144
145 validate_status_stopped(status, SIGTRAP);
146
147 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
148 "child\n");
149 SYSCALL_REQUIRE(
150 ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
151
152 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
153 DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
154 "si_errno=%#x\n",
155 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
156 info.psi_siginfo.si_errno);
157
158 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
159 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
160
161 SYSCALL_REQUIRE(
162 ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
163
164 ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
165 "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
166
167 lid = state.pe_lwp;
168 DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
169
170 *FIND_EVENT_COUNT(traced_lwps, lid) += 1;
171
172 DPRINTF("Before resuming the child process where it left off "
173 "and without signal to be sent\n");
174 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
175 }
176
177 for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
178 DPRINTF("Before calling %s() for the child - expected stopped "
179 "SIGTRAP\n", TWAIT_FNAME);
180 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
181 child);
182
183 validate_status_stopped(status, SIGTRAP);
184
185 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
186 "child\n");
187 SYSCALL_REQUIRE(
188 ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
189
190 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
191 DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
192 "si_errno=%#x\n",
193 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
194 info.psi_siginfo.si_errno);
195
196 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
197 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
198
199 SYSCALL_REQUIRE(
200 ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
201
202 ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
203 "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
204
205 lid = state.pe_lwp;
206 DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
207
208 if (trace_create) {
209 int *count = FIND_EVENT_COUNT(traced_lwps, lid);
210 ATF_REQUIRE_EQ(*count, 1);
211 *count = 0;
212 }
213
214 DPRINTF("Before resuming the child process where it left off "
215 "and without signal to be sent\n");
216 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
217 }
218
219 kill(child, SIGKILL);
220
221 DPRINTF("Before calling %s() for the child - expected exited\n",
222 TWAIT_FNAME);
223 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
224
225 validate_status_signaled(status, SIGKILL, 0);
226
227 DPRINTF("Before calling %s() for the child - expected no process\n",
228 TWAIT_FNAME);
229 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
230 }
231
232 #define TRACE_THREADS(test, trace_create, trace_exit, mask) \
233 ATF_TC(test); \
234 ATF_TC_HEAD(test, tc) \
235 { \
236 atf_tc_set_md_var(tc, "descr", \
237 "Verify spawning threads with%s tracing LWP create and" \
238 "with%s tracing LWP exit", trace_create ? "" : "out", \
239 trace_exit ? "" : "out"); \
240 } \
241 \
242 ATF_TC_BODY(test, tc) \
243 { \
244 \
245 trace_threads(trace_create, trace_exit, mask); \
246 }
247
248 TRACE_THREADS(trace_thread_nolwpevents, false, false, false)
249 TRACE_THREADS(trace_thread_lwpexit, false, true, false)
250 TRACE_THREADS(trace_thread_lwpcreate, true, false, false)
251 TRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true, false)
252
253 TRACE_THREADS(trace_thread_lwpexit_masked_sigtrap, false, true, true)
254 TRACE_THREADS(trace_thread_lwpcreate_masked_sigtrap, true, false, true)
255 TRACE_THREADS(trace_thread_lwpcreate_and_exit_masked_sigtrap, true, true, true)
256
257 /// ----------------------------------------------------------------------------
258
259 static void *
260 thread_and_exec_thread_cb(void *arg __unused)
261 {
262
263 execlp("/bin/echo", "/bin/echo", NULL);
264
265 abort();
266 }
267
268 static void
269 threads_and_exec(void)
270 {
271 const int sigval = SIGSTOP;
272 pid_t child, wpid;
273 #if defined(TWAIT_HAVE_STATUS)
274 int status;
275 #endif
276 ptrace_state_t state;
277 const int slen = sizeof(state);
278 ptrace_event_t event;
279 const int elen = sizeof(event);
280 struct ptrace_siginfo info;
281
282 pthread_t t;
283 lwpid_t lid;
284
285 DPRINTF("Before forking process PID=%d\n", getpid());
286 SYSCALL_REQUIRE((child = fork()) != -1);
287 if (child == 0) {
288 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
289 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
290
291 DPRINTF("Before raising %s from child\n", strsignal(sigval));
292 FORKEE_ASSERT(raise(sigval) == 0);
293
294 FORKEE_ASSERT(pthread_create(&t, NULL,
295 thread_and_exec_thread_cb, NULL) == 0);
296
297 for (;;)
298 continue;
299
300 FORKEE_ASSERT(0 && "Not reached");
301 }
302 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
303
304 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
305 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
306
307 validate_status_stopped(status, sigval);
308
309 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
310 SYSCALL_REQUIRE(
311 ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
312
313 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
314 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
315 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
316 info.psi_siginfo.si_errno);
317
318 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
319 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
320
321 DPRINTF("Set LWP event mask for the child %d\n", child);
322 memset(&event, 0, sizeof(event));
323 event.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
324 SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
325
326 DPRINTF("Before resuming the child process where it left off and "
327 "without signal to be sent\n");
328 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
329
330 DPRINTF("Before calling %s() for the child - expected stopped "
331 "SIGTRAP\n", TWAIT_FNAME);
332 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
333 child);
334
335 validate_status_stopped(status, SIGTRAP);
336
337 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
338 "child\n");
339 SYSCALL_REQUIRE(
340 ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
341
342 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
343 DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
344 "si_errno=%#x\n",
345 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
346 info.psi_siginfo.si_errno);
347
348 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
349 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
350
351 SYSCALL_REQUIRE(
352 ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
353
354 ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
355 "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
356
357 lid = state.pe_lwp;
358 DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
359
360 DPRINTF("Before resuming the child process where it left off "
361 "and without signal to be sent\n");
362 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
363
364 DPRINTF("Before calling %s() for the child - expected stopped "
365 "SIGTRAP\n", TWAIT_FNAME);
366 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
367 child);
368
369 validate_status_stopped(status, SIGTRAP);
370
371 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
372 "child\n");
373 SYSCALL_REQUIRE(
374 ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
375
376 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
377 DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
378 "si_errno=%#x\n",
379 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
380 info.psi_siginfo.si_errno);
381
382 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
383 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
384
385 SYSCALL_REQUIRE(
386 ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
387
388 ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
389 "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
390
391 lid = state.pe_lwp;
392 DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
393
394 DPRINTF("Before resuming the child process where it left off "
395 "and without signal to be sent\n");
396 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
397
398 DPRINTF("Before calling %s() for the child - expected stopped "
399 "SIGTRAP\n", TWAIT_FNAME);
400 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
401 child);
402
403 validate_status_stopped(status, SIGTRAP);
404
405 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
406 "child\n");
407 SYSCALL_REQUIRE(
408 ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
409
410 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
411 DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
412 "si_errno=%#x\n",
413 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
414 info.psi_siginfo.si_errno);
415
416 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
417 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
418
419 SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
420
421 DPRINTF("Before calling %s() for the child - expected exited\n",
422 TWAIT_FNAME);
423 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
424
425 validate_status_signaled(status, SIGKILL, 0);
426
427 DPRINTF("Before calling %s() for the child - expected no process\n",
428 TWAIT_FNAME);
429 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
430 }
431
432 ATF_TC(threads_and_exec);
433 ATF_TC_HEAD(threads_and_exec, tc)
434 {
435 atf_tc_set_md_var(tc, "descr",
436 "Verify that multithreaded application on exec() will report "
437 "LWP_EXIT events");
438 }
439
440 ATF_TC_BODY(threads_and_exec, tc)
441 {
442
443 threads_and_exec();
444 }
445
446 /// ----------------------------------------------------------------------------
447
448 ATF_TC(suspend_no_deadlock);
449 ATF_TC_HEAD(suspend_no_deadlock, tc)
450 {
451 atf_tc_set_md_var(tc, "descr",
452 "Verify that the while the only thread within a process is "
453 "suspended, the whole process cannot be unstopped");
454 }
455
456 ATF_TC_BODY(suspend_no_deadlock, tc)
457 {
458 const int exitval = 5;
459 const int sigval = SIGSTOP;
460 pid_t child, wpid;
461 #if defined(TWAIT_HAVE_STATUS)
462 int status;
463 #endif
464 struct ptrace_siginfo psi;
465
466 DPRINTF("Before forking process PID=%d\n", getpid());
467 SYSCALL_REQUIRE((child = fork()) != -1);
468 if (child == 0) {
469 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
470 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
471
472 DPRINTF("Before raising %s from child\n", strsignal(sigval));
473 FORKEE_ASSERT(raise(sigval) == 0);
474
475 DPRINTF("Before exiting of the child process\n");
476 _exit(exitval);
477 }
478 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
479
480 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
481 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
482
483 validate_status_stopped(status, sigval);
484
485 DPRINTF("Before reading siginfo and lwpid_t\n");
486 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
487
488 DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
489 SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
490
491 DPRINTF("Before resuming the child process where it left off and "
492 "without signal to be sent\n");
493 ATF_REQUIRE_ERRNO(EDEADLK,
494 ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
495
496 DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
497 SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
498
499 DPRINTF("Before resuming the child process where it left off and "
500 "without signal to be sent\n");
501 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
502
503 DPRINTF("Before calling %s() for the child - expected exited\n",
504 TWAIT_FNAME);
505 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
506
507 validate_status_exited(status, exitval);
508
509 DPRINTF("Before calling %s() for the child - expected no process\n",
510 TWAIT_FNAME);
511 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
512 }
513
514 /// ----------------------------------------------------------------------------
515
516 static pthread_barrier_t barrier1_resume;
517 static pthread_barrier_t barrier2_resume;
518
519 static void *
520 resume_thread(void *arg)
521 {
522
523 raise(SIGUSR1);
524
525 pthread_barrier_wait(&barrier1_resume);
526
527 /* Debugger will suspend the process here */
528
529 pthread_barrier_wait(&barrier2_resume);
530
531 raise(SIGUSR2);
532
533 return infinite_thread(arg);
534 }
535
536 ATF_TC(resume);
537 ATF_TC_HEAD(resume, tc)
538 {
539 atf_tc_set_md_var(tc, "descr",
540 "Verify that a thread can be suspended by a debugger and later "
541 "resumed by the debugger");
542 }
543
544 ATF_TC_BODY(resume, tc)
545 {
546 const int sigval = SIGSTOP;
547 pid_t child, wpid;
548 #if defined(TWAIT_HAVE_STATUS)
549 int status;
550 #endif
551 lwpid_t lid;
552 struct ptrace_siginfo psi;
553 pthread_t t;
554
555 DPRINTF("Before forking process PID=%d\n", getpid());
556 SYSCALL_REQUIRE((child = fork()) != -1);
557 if (child == 0) {
558 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
559 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
560
561 pthread_barrier_init(&barrier1_resume, NULL, 2);
562 pthread_barrier_init(&barrier2_resume, NULL, 2);
563
564 DPRINTF("Before raising %s from child\n", strsignal(sigval));
565 FORKEE_ASSERT(raise(sigval) == 0);
566
567 DPRINTF("Before creating new thread in child\n");
568 FORKEE_ASSERT(pthread_create(&t, NULL, resume_thread, NULL) == 0);
569
570 pthread_barrier_wait(&barrier1_resume);
571
572 pthread_barrier_wait(&barrier2_resume);
573
574 infinite_thread(NULL);
575 }
576 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
577
578 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
579 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
580
581 validate_status_stopped(status, sigval);
582
583 DPRINTF("Before resuming the child process where it left off and "
584 "without signal to be sent\n");
585 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
586
587 DPRINTF("Before calling %s() for the child - expected stopped "
588 "SIGUSR1\n", TWAIT_FNAME);
589 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
590
591 validate_status_stopped(status, SIGUSR1);
592
593 DPRINTF("Before reading siginfo and lwpid_t\n");
594 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
595
596 DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
597 SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
598
599 lid = psi.psi_lwpid;
600
601 DPRINTF("Before resuming the child process where it left off and "
602 "without signal to be sent\n");
603 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
604
605 DPRINTF("Before suspending the parent for 1 second, we expect no signals\n");
606 SYSCALL_REQUIRE(sleep(1) == 0);
607
608 #if defined(TWAIT_HAVE_OPTIONS)
609 DPRINTF("Before calling %s() for the child - expected no status\n",
610 TWAIT_FNAME);
611 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, WNOHANG), 0);
612 #endif
613
614 DPRINTF("Before resuming the child process where it left off and "
615 "without signal to be sent\n");
616 SYSCALL_REQUIRE(ptrace(PT_STOP, child, NULL, 0) != -1);
617
618 DPRINTF("Before calling %s() for the child - expected stopped "
619 "SIGSTOP\n", TWAIT_FNAME);
620 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
621
622 validate_status_stopped(status, SIGSTOP);
623
624 DPRINTF("Before resuming LWP %d\n", lid);
625 SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, lid) != -1);
626
627 DPRINTF("Before resuming the child process where it left off and "
628 "without signal to be sent\n");
629 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
630
631 DPRINTF("Before calling %s() for the child - expected stopped "
632 "SIGUSR2\n", TWAIT_FNAME);
633 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
634
635 validate_status_stopped(status, SIGUSR2);
636
637 DPRINTF("Before resuming the child process where it left off and "
638 "without signal to be sent\n");
639 SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
640
641 DPRINTF("Before calling %s() for the child - expected exited\n",
642 TWAIT_FNAME);
643 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
644
645 validate_status_signaled(status, SIGKILL, 0);
646
647 DPRINTF("Before calling %s() for the child - expected no process\n",
648 TWAIT_FNAME);
649 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
650 }
651
652 /// ----------------------------------------------------------------------------
653
654 #if defined(TWAIT_HAVE_STATUS)
655
656 #define THREAD_CONCURRENT_BREAKPOINT_NUM 50
657 #define THREAD_CONCURRENT_SIGNALS_NUM 50
658 #define THREAD_CONCURRENT_WATCHPOINT_NUM 50
659
660 /* List of signals to use for the test */
661 const int thread_concurrent_signals_list[] = {
662 SIGIO,
663 SIGXCPU,
664 SIGXFSZ,
665 SIGVTALRM,
666 SIGPROF,
667 SIGWINCH,
668 SIGINFO,
669 SIGUSR1,
670 SIGUSR2
671 };
672
673 enum thread_concurrent_signal_handling {
674 /* the signal is discarded by debugger */
675 TCSH_DISCARD,
676 /* the handler is set to SIG_IGN */
677 TCSH_SIG_IGN,
678 /* an actual handler is used */
679 TCSH_HANDLER
680 };
681
682 static pthread_barrier_t thread_concurrent_barrier;
683 static pthread_key_t thread_concurrent_key;
684 static uint32_t thread_concurrent_watchpoint_var = 0;
685
686 static void *
687 thread_concurrent_breakpoint_thread(void *arg)
688 {
689 static volatile int watchme = 1;
690 pthread_barrier_wait(&thread_concurrent_barrier);
691 DPRINTF("Before entering breakpoint func from LWP %d\n", _lwp_self());
692 check_happy(watchme);
693 return NULL;
694 }
695
696 static void
697 thread_concurrent_sig_handler(int sig)
698 {
699 void *tls_val = pthread_getspecific(thread_concurrent_key);
700 DPRINTF("Before increment, LWP %d tls_val=%p\n", _lwp_self(), tls_val);
701 FORKEE_ASSERT(pthread_setspecific(thread_concurrent_key,
702 (void*)((uintptr_t)tls_val + 1)) == 0);
703 }
704
705 static void *
706 thread_concurrent_signals_thread(void *arg)
707 {
708 int sigval = thread_concurrent_signals_list[
709 _lwp_self() % __arraycount(thread_concurrent_signals_list)];
710 enum thread_concurrent_signal_handling *signal_handle = arg;
711 void *tls_val;
712
713 pthread_barrier_wait(&thread_concurrent_barrier);
714 DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval),
715 _lwp_self());
716 pthread_kill(pthread_self(), sigval);
717 if (*signal_handle == TCSH_HANDLER) {
718 tls_val = pthread_getspecific(thread_concurrent_key);
719 DPRINTF("After raising, LWP %d tls_val=%p\n", _lwp_self(), tls_val);
720 FORKEE_ASSERT(tls_val == (void*)1);
721 }
722 return NULL;
723 }
724
725 static void *
726 thread_concurrent_watchpoint_thread(void *arg)
727 {
728 pthread_barrier_wait(&thread_concurrent_barrier);
729 DPRINTF("Before modifying var from LWP %d\n", _lwp_self());
730 thread_concurrent_watchpoint_var = 1;
731 return NULL;
732 }
733
734 #if defined(__i386__) || defined(__x86_64__)
735 enum thread_concurrent_sigtrap_event {
736 TCSE_UNKNOWN,
737 TCSE_BREAKPOINT,
738 TCSE_WATCHPOINT
739 };
740
741 static void
742 thread_concurrent_lwp_setup(pid_t child, lwpid_t lwpid);
743 static enum thread_concurrent_sigtrap_event
744 thread_concurrent_handle_sigtrap(pid_t child, ptrace_siginfo_t *info);
745 #endif
746
747 static void
748 thread_concurrent_test(enum thread_concurrent_signal_handling signal_handle,
749 int breakpoint_threads, int signal_threads, int watchpoint_threads)
750 {
751 const int exitval = 5;
752 const int sigval = SIGSTOP;
753 pid_t child, wpid;
754 int status;
755 struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM]
756 = {{0, 0}};
757 struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM]
758 = {{0, 0}};
759 struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM]
760 = {{0, 0}};
761 ptrace_event_t event;
762 int i;
763
764 #if defined(HAVE_DBREGS)
765 if (!can_we_set_dbregs()) {
766 atf_tc_skip("Either run this test as root or set sysctl(3) "
767 "security.models.extensions.user_set_dbregs to 1");
768 }
769 #endif
770
771 atf_tc_skip("PR kern/54960");
772
773 /* Protect against out-of-bounds array access. */
774 ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM);
775 ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM);
776 ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM);
777
778 DPRINTF("Before forking process PID=%d\n", getpid());
779 SYSCALL_REQUIRE((child = fork()) != -1);
780 if (child == 0) {
781 pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM];
782 pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM];
783 pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM];
784
785 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
786 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
787
788 DPRINTF("Before raising %s from child\n", strsignal(sigval));
789 FORKEE_ASSERT(raise(sigval) == 0);
790
791 if (signal_handle != TCSH_DISCARD) {
792 struct sigaction sa;
793 unsigned int j;
794
795 memset(&sa, 0, sizeof(sa));
796 if (signal_handle == TCSH_SIG_IGN)
797 sa.sa_handler = SIG_IGN;
798 else
799 sa.sa_handler = thread_concurrent_sig_handler;
800 sigemptyset(&sa.sa_mask);
801
802 for (j = 0;
803 j < __arraycount(thread_concurrent_signals_list);
804 j++)
805 FORKEE_ASSERT(sigaction(
806 thread_concurrent_signals_list[j], &sa, NULL)
807 != -1);
808 }
809
810 DPRINTF("Before starting threads from the child\n");
811 FORKEE_ASSERT(pthread_barrier_init(
812 &thread_concurrent_barrier, NULL,
813 breakpoint_threads + signal_threads + watchpoint_threads)
814 == 0);
815 FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL)
816 == 0);
817
818 for (i = 0; i < signal_threads; i++) {
819 FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL,
820 thread_concurrent_signals_thread,
821 &signal_handle) == 0);
822 }
823 for (i = 0; i < breakpoint_threads; i++) {
824 FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL,
825 thread_concurrent_breakpoint_thread, NULL) == 0);
826 }
827 for (i = 0; i < watchpoint_threads; i++) {
828 FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL,
829 thread_concurrent_watchpoint_thread, NULL) == 0);
830 }
831
832 DPRINTF("Before joining threads from the child\n");
833 for (i = 0; i < watchpoint_threads; i++) {
834 FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0);
835 }
836 for (i = 0; i < breakpoint_threads; i++) {
837 FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0);
838 }
839 for (i = 0; i < signal_threads; i++) {
840 FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0);
841 }
842
843 FORKEE_ASSERT(pthread_key_delete(thread_concurrent_key) == 0);
844 FORKEE_ASSERT(pthread_barrier_destroy(
845 &thread_concurrent_barrier) == 0);
846
847 DPRINTF("Before exiting of the child process\n");
848 _exit(exitval);
849 }
850 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
851
852 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
853 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
854
855 validate_status_stopped(status, sigval);
856
857 DPRINTF("Set LWP event mask for the child process\n");
858 memset(&event, 0, sizeof(event));
859 event.pe_set_event |= PTRACE_LWP_CREATE;
860 SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event))
861 != -1);
862
863 DPRINTF("Before resuming the child process where it left off\n");
864 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
865
866 DPRINTF("Before entering signal collection loop\n");
867 while (1) {
868 ptrace_siginfo_t info;
869
870 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
871 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
872 child);
873 if (WIFEXITED(status))
874 break;
875 /* Note: we use validate_status_stopped() to get nice error
876 * message. Signal is irrelevant since it won't be reached.
877 */
878 else if (!WIFSTOPPED(status))
879 validate_status_stopped(status, 0);
880
881 DPRINTF("Before calling PT_GET_SIGINFO\n");
882 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
883 sizeof(info)) != -1);
884
885 DPRINTF("Received signal %d from LWP %d (wait: %d)\n",
886 info.psi_siginfo.si_signo, info.psi_lwpid,
887 WSTOPSIG(status));
888
889 ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status),
890 "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid,
891 WSTOPSIG(status), info.psi_siginfo.si_signo);
892
893 if (WSTOPSIG(status) != SIGTRAP) {
894 int expected_sig =
895 thread_concurrent_signals_list[info.psi_lwpid %
896 __arraycount(thread_concurrent_signals_list)];
897 ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig,
898 "lwp=%d, expected %d, got %d", info.psi_lwpid,
899 expected_sig, WSTOPSIG(status));
900
901 *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1;
902 } else if (info.psi_siginfo.si_code == TRAP_LWP) {
903 #if defined(__i386__) || defined(__x86_64__)
904 thread_concurrent_lwp_setup(child, info.psi_lwpid);
905 #endif
906 } else {
907 #if defined(__i386__) || defined(__x86_64__)
908 switch (thread_concurrent_handle_sigtrap(child, &info)) {
909 case TCSE_UNKNOWN:
910 /* already reported inside the function */
911 break;
912 case TCSE_BREAKPOINT:
913 *FIND_EVENT_COUNT(bp_counts,
914 info.psi_lwpid) += 1;
915 break;
916 case TCSE_WATCHPOINT:
917 *FIND_EVENT_COUNT(wp_counts,
918 info.psi_lwpid) += 1;
919 break;
920 }
921 #else
922 ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n",
923 info.psi_siginfo.si_code);
924 #endif
925 }
926
927 DPRINTF("Before resuming the child process\n");
928 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
929 signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP
930 ? WSTOPSIG(status) : 0) != -1);
931 }
932
933 for (i = 0; i < signal_threads; i++)
934 ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1,
935 "signal_counts[%d].lec_count=%d; lec_lwp=%d",
936 i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
937 for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++)
938 ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0,
939 "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d",
940 i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
941
942 for (i = 0; i < breakpoint_threads; i++)
943 ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1,
944 "bp_counts[%d].lec_count=%d; lec_lwp=%d",
945 i, bp_counts[i].lec_count, bp_counts[i].lec_lwp);
946 for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++)
947 ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0,
948 "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d",
949 i, bp_counts[i].lec_count, bp_counts[i].lec_lwp);
950
951 for (i = 0; i < watchpoint_threads; i++)
952 ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1,
953 "wp_counts[%d].lec_count=%d; lec_lwp=%d",
954 i, wp_counts[i].lec_count, wp_counts[i].lec_lwp);
955 for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++)
956 ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0,
957 "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d",
958 i, wp_counts[i].lec_count, wp_counts[i].lec_lwp);
959
960 validate_status_exited(status, exitval);
961 }
962
963 #define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr) \
964 ATF_TC(test); \
965 ATF_TC_HEAD(test, tc) \
966 { \
967 atf_tc_set_md_var(tc, "descr", descr); \
968 } \
969 \
970 ATF_TC_BODY(test, tc) \
971 { \
972 thread_concurrent_test(sig_hdl, bps, sigs, wps); \
973 }
974
975 THREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD,
976 0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
977 "Verify that concurrent signals issued to a single thread are reported "
978 "correctly");
979 THREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN,
980 0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
981 "Verify that concurrent signals issued to a single thread are reported "
982 "correctly and passed back to SIG_IGN handler");
983 THREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER,
984 0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
985 "Verify that concurrent signals issued to a single thread are reported "
986 "correctly and passed back to a handler function");
987
988 #if defined(__i386__) || defined(__x86_64__)
989 THREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD,
990 THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0,
991 "Verify that concurrent breakpoints are reported correctly");
992 THREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD,
993 0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM,
994 "Verify that concurrent breakpoints are reported correctly");
995 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD,
996 THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM,
997 "Verify that concurrent breakpoints and watchpoints are reported "
998 "correctly");
999
1000 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD,
1001 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1002 "Verify that concurrent breakpoints and signals are reported correctly");
1003 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN,
1004 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1005 "Verify that concurrent breakpoints and signals are reported correctly "
1006 "and passed back to SIG_IGN handler");
1007 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER,
1008 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1009 "Verify that concurrent breakpoints and signals are reported correctly "
1010 "and passed back to a handler function");
1011
1012 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD,
1013 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1014 "Verify that concurrent watchpoints and signals are reported correctly");
1015 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN,
1016 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1017 "Verify that concurrent watchpoints and signals are reported correctly "
1018 "and passed back to SIG_IGN handler");
1019 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER,
1020 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1021 "Verify that concurrent watchpoints and signals are reported correctly "
1022 "and passed back to a handler function");
1023
1024 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD,
1025 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1026 THREAD_CONCURRENT_WATCHPOINT_NUM,
1027 "Verify that concurrent breakpoints, watchpoints and signals are reported "
1028 "correctly");
1029 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN,
1030 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1031 THREAD_CONCURRENT_WATCHPOINT_NUM,
1032 "Verify that concurrent breakpoints, watchpoints and signals are reported "
1033 "correctly and passed back to SIG_IGN handler");
1034 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER,
1035 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1036 THREAD_CONCURRENT_WATCHPOINT_NUM,
1037 "Verify that concurrent breakpoints, watchpoints and signals are reported "
1038 "correctly and passed back to a handler function");
1039 #endif
1040
1041 #endif /*defined(TWAIT_HAVE_STATUS)*/
1042
1043 #define ATF_TP_ADD_TCS_PTRACE_WAIT_THREADS() \
1044 ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); \
1045 ATF_TP_ADD_TC(tp, trace_thread_lwpexit); \
1046 ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); \
1047 ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); \
1048 ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap); \
1049 ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap); \
1050 ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap); \
1051 ATF_TP_ADD_TC(tp, threads_and_exec); \
1052 ATF_TP_ADD_TC(tp, suspend_no_deadlock); \
1053 ATF_TP_ADD_TC(tp, resume); \
1054 ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals); \
1055 ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals_sig_ign); \
1056 ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals_handler); \
1057 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_breakpoints); \
1058 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_watchpoints); \
1059 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp); \
1060 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig); \
1061 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig_sig_ign); \
1062 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig_handler); \
1063 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig); \
1064 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig_sig_ign); \
1065 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig_handler); \
1066 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig); \
1067 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig_sig_ign); \
1068 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig_handler);
1069