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