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