t_ptrace_threads_wait.h revision 1.3 1 /* $NetBSD: t_ptrace_threads_wait.h,v 1.3 2025/05/02 02:24:44 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_PTHREAD(pthread_create(&t, NULL,
295 thread_and_exec_thread_cb, NULL));
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_PTHREAD(pthread_create(&t, NULL, resume_thread, NULL));
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_PTHREAD(pthread_setspecific(thread_concurrent_key,
702 (void*)((uintptr_t)tls_val + 1)));
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_PTHREAD(pthread_barrier_init(
812 &thread_concurrent_barrier, NULL,
813 breakpoint_threads + signal_threads + watchpoint_threads));
814 FORKEE_PTHREAD(pthread_key_create(&thread_concurrent_key,
815 NULL));
816
817 for (i = 0; i < signal_threads; i++) {
818 FORKEE_PTHREAD(pthread_create(&sig_threads[i], NULL,
819 thread_concurrent_signals_thread,
820 &signal_handle));
821 }
822 for (i = 0; i < breakpoint_threads; i++) {
823 FORKEE_PTHREAD(pthread_create(&bp_threads[i], NULL,
824 thread_concurrent_breakpoint_thread, NULL));
825 }
826 for (i = 0; i < watchpoint_threads; i++) {
827 FORKEE_PTHREAD(pthread_create(&wp_threads[i], NULL,
828 thread_concurrent_watchpoint_thread, NULL));
829 }
830
831 DPRINTF("Before joining threads from the child\n");
832 for (i = 0; i < watchpoint_threads; i++) {
833 FORKEE_PTHREAD(pthread_join(wp_threads[i], NULL));
834 }
835 for (i = 0; i < breakpoint_threads; i++) {
836 FORKEE_PTHREAD(pthread_join(bp_threads[i], NULL));
837 }
838 for (i = 0; i < signal_threads; i++) {
839 FORKEE_PTHREAD(pthread_join(sig_threads[i], NULL));
840 }
841
842 FORKEE_PTHREAD(pthread_key_delete(thread_concurrent_key));
843 FORKEE_PTHREAD(pthread_barrier_destroy(
844 &thread_concurrent_barrier));
845
846 DPRINTF("Before exiting of the child process\n");
847 _exit(exitval);
848 }
849 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
850
851 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
852 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
853
854 validate_status_stopped(status, sigval);
855
856 DPRINTF("Set LWP event mask for the child process\n");
857 memset(&event, 0, sizeof(event));
858 event.pe_set_event |= PTRACE_LWP_CREATE;
859 SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event))
860 != -1);
861
862 DPRINTF("Before resuming the child process where it left off\n");
863 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
864
865 DPRINTF("Before entering signal collection loop\n");
866 while (1) {
867 ptrace_siginfo_t info;
868
869 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
870 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
871 child);
872 if (WIFEXITED(status))
873 break;
874 /* Note: we use validate_status_stopped() to get nice error
875 * message. Signal is irrelevant since it won't be reached.
876 */
877 else if (!WIFSTOPPED(status))
878 validate_status_stopped(status, 0);
879
880 DPRINTF("Before calling PT_GET_SIGINFO\n");
881 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
882 sizeof(info)) != -1);
883
884 DPRINTF("Received signal %d from LWP %d (wait: %d)\n",
885 info.psi_siginfo.si_signo, info.psi_lwpid,
886 WSTOPSIG(status));
887
888 ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status),
889 "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid,
890 WSTOPSIG(status), info.psi_siginfo.si_signo);
891
892 if (WSTOPSIG(status) != SIGTRAP) {
893 int expected_sig =
894 thread_concurrent_signals_list[info.psi_lwpid %
895 __arraycount(thread_concurrent_signals_list)];
896 ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig,
897 "lwp=%d, expected %d, got %d", info.psi_lwpid,
898 expected_sig, WSTOPSIG(status));
899
900 *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1;
901 } else if (info.psi_siginfo.si_code == TRAP_LWP) {
902 #if defined(__i386__) || defined(__x86_64__)
903 thread_concurrent_lwp_setup(child, info.psi_lwpid);
904 #endif
905 } else {
906 #if defined(__i386__) || defined(__x86_64__)
907 switch (thread_concurrent_handle_sigtrap(child, &info)) {
908 case TCSE_UNKNOWN:
909 /* already reported inside the function */
910 break;
911 case TCSE_BREAKPOINT:
912 *FIND_EVENT_COUNT(bp_counts,
913 info.psi_lwpid) += 1;
914 break;
915 case TCSE_WATCHPOINT:
916 *FIND_EVENT_COUNT(wp_counts,
917 info.psi_lwpid) += 1;
918 break;
919 }
920 #else
921 ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n",
922 info.psi_siginfo.si_code);
923 #endif
924 }
925
926 DPRINTF("Before resuming the child process\n");
927 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
928 signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP
929 ? WSTOPSIG(status) : 0) != -1);
930 }
931
932 for (i = 0; i < signal_threads; i++)
933 ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1,
934 "signal_counts[%d].lec_count=%d; lec_lwp=%d",
935 i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
936 for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++)
937 ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0,
938 "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d",
939 i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
940
941 for (i = 0; i < breakpoint_threads; i++)
942 ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1,
943 "bp_counts[%d].lec_count=%d; lec_lwp=%d",
944 i, bp_counts[i].lec_count, bp_counts[i].lec_lwp);
945 for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++)
946 ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0,
947 "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d",
948 i, bp_counts[i].lec_count, bp_counts[i].lec_lwp);
949
950 for (i = 0; i < watchpoint_threads; i++)
951 ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1,
952 "wp_counts[%d].lec_count=%d; lec_lwp=%d",
953 i, wp_counts[i].lec_count, wp_counts[i].lec_lwp);
954 for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++)
955 ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0,
956 "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d",
957 i, wp_counts[i].lec_count, wp_counts[i].lec_lwp);
958
959 validate_status_exited(status, exitval);
960 }
961
962 #define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr) \
963 ATF_TC(test); \
964 ATF_TC_HEAD(test, tc) \
965 { \
966 atf_tc_set_md_var(tc, "descr", descr); \
967 } \
968 \
969 ATF_TC_BODY(test, tc) \
970 { \
971 thread_concurrent_test(sig_hdl, bps, sigs, wps); \
972 }
973
974 THREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD,
975 0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
976 "Verify that concurrent signals issued to a single thread are reported "
977 "correctly");
978 THREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN,
979 0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
980 "Verify that concurrent signals issued to a single thread are reported "
981 "correctly and passed back to SIG_IGN handler");
982 THREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER,
983 0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
984 "Verify that concurrent signals issued to a single thread are reported "
985 "correctly and passed back to a handler function");
986
987 #if defined(__i386__) || defined(__x86_64__)
988 THREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD,
989 THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0,
990 "Verify that concurrent breakpoints are reported correctly");
991 THREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD,
992 0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM,
993 "Verify that concurrent breakpoints are reported correctly");
994 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD,
995 THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM,
996 "Verify that concurrent breakpoints and watchpoints are reported "
997 "correctly");
998
999 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD,
1000 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1001 "Verify that concurrent breakpoints and signals are reported correctly");
1002 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN,
1003 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1004 "Verify that concurrent breakpoints and signals are reported correctly "
1005 "and passed back to SIG_IGN handler");
1006 THREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER,
1007 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
1008 "Verify that concurrent breakpoints and signals are reported correctly "
1009 "and passed back to a handler function");
1010
1011 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD,
1012 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1013 "Verify that concurrent watchpoints and signals are reported correctly");
1014 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN,
1015 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1016 "Verify that concurrent watchpoints and signals are reported correctly "
1017 "and passed back to SIG_IGN handler");
1018 THREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER,
1019 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
1020 "Verify that concurrent watchpoints and signals are reported correctly "
1021 "and passed back to a handler function");
1022
1023 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD,
1024 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1025 THREAD_CONCURRENT_WATCHPOINT_NUM,
1026 "Verify that concurrent breakpoints, watchpoints and signals are reported "
1027 "correctly");
1028 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN,
1029 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1030 THREAD_CONCURRENT_WATCHPOINT_NUM,
1031 "Verify that concurrent breakpoints, watchpoints and signals are reported "
1032 "correctly and passed back to SIG_IGN handler");
1033 THREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER,
1034 THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
1035 THREAD_CONCURRENT_WATCHPOINT_NUM,
1036 "Verify that concurrent breakpoints, watchpoints and signals are reported "
1037 "correctly and passed back to a handler function");
1038 #endif
1039
1040 #endif /*defined(TWAIT_HAVE_STATUS)*/
1041
1042 #define ATF_TP_ADD_TCS_PTRACE_WAIT_THREADS() \
1043 ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); \
1044 ATF_TP_ADD_TC(tp, trace_thread_lwpexit); \
1045 ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); \
1046 ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); \
1047 ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap); \
1048 ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap); \
1049 ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap); \
1050 ATF_TP_ADD_TC(tp, threads_and_exec); \
1051 ATF_TP_ADD_TC(tp, suspend_no_deadlock); \
1052 ATF_TP_ADD_TC(tp, resume); \
1053 ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals); \
1054 ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals_sig_ign); \
1055 ATF_TP_ADD_TC_HAVE_STATUS(tp, thread_concurrent_signals_handler); \
1056 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_breakpoints); \
1057 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_watchpoints); \
1058 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp); \
1059 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig); \
1060 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig_sig_ign); \
1061 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_sig_handler); \
1062 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig); \
1063 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig_sig_ign); \
1064 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_wp_sig_handler); \
1065 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig); \
1066 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig_sig_ign); \
1067 ATF_TP_ADD_TC_HAVE_STATUS_X86(tp, thread_concurrent_bp_wp_sig_handler);
1068