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