]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - tests/sys/kern/reaper.c
MFC r309957: Add tests for reaper receiving SIGCHLD (r309886).
[FreeBSD/stable/10.git] / tests / sys / kern / reaper.c
1 /*-
2  * Copyright (c) 2016 Jilles Tjoelker
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/procctl.h>
31 #include <sys/wait.h>
32
33 #include <atf-c.h>
34 #include <errno.h>
35 #include <signal.h>
36 #include <unistd.h>
37
38 static void
39 dummy_sighandler(int sig __unused, siginfo_t *info __unused, void *ctx __unused)
40 {
41 }
42
43 ATF_TC_WITHOUT_HEAD(reaper_wait_child_first);
44 ATF_TC_BODY(reaper_wait_child_first, tc)
45 {
46         pid_t parent, child, grandchild, pid;
47         int status, r;
48         int pip[2];
49
50         /* Be paranoid. */
51         pid = waitpid(-1, NULL, WNOHANG);
52         ATF_REQUIRE(pid == -1 && errno == ECHILD);
53
54         parent = getpid();
55         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
56         ATF_REQUIRE_EQ(0, r);
57
58         r = pipe(pip);
59         ATF_REQUIRE_EQ(0, r);
60
61         child = fork();
62         ATF_REQUIRE(child != -1);
63         if (child == 0) {
64                 if (close(pip[1]) != 0)
65                         _exit(100);
66                 grandchild = fork();
67                 if (grandchild == -1)
68                         _exit(101);
69                 else if (grandchild == 0) {
70                         if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
71                                 _exit(102);
72                         if (getppid() != parent)
73                                 _exit(103);
74                         _exit(2);
75                 } else
76                         _exit(3);
77         }
78
79         pid = waitpid(child, &status, 0);
80         ATF_REQUIRE_EQ(child, pid);
81         r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
82         ATF_CHECK_EQ(3, r);
83
84         r = close(pip[1]);
85         ATF_REQUIRE_EQ(0, r);
86
87         pid = waitpid(-1, &status, 0);
88         ATF_REQUIRE(pid > 0 && pid != child);
89         r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
90         ATF_CHECK_EQ(2, r);
91
92         r = close(pip[0]);
93         ATF_REQUIRE_EQ(0, r);
94 }
95
96 ATF_TC_WITHOUT_HEAD(reaper_wait_grandchild_first);
97 ATF_TC_BODY(reaper_wait_grandchild_first, tc)
98 {
99         pid_t parent, child, grandchild, pid;
100         int status, r;
101
102         /* Be paranoid. */
103         pid = waitpid(-1, NULL, WNOHANG);
104         ATF_REQUIRE(pid == -1 && errno == ECHILD);
105
106         parent = getpid();
107         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
108         ATF_REQUIRE_EQ(0, r);
109
110         child = fork();
111         ATF_REQUIRE(child != -1);
112         if (child == 0) {
113                 grandchild = fork();
114                 if (grandchild == -1)
115                         _exit(101);
116                 else if (grandchild == 0)
117                         _exit(2);
118                 else {
119                         if (waitid(P_PID, grandchild, NULL,
120                             WNOWAIT | WEXITED) != 0)
121                                 _exit(102);
122                         _exit(3);
123                 }
124         }
125
126         pid = waitpid(child, &status, 0);
127         ATF_REQUIRE_EQ(child, pid);
128         r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
129         ATF_CHECK_EQ(3, r);
130
131         pid = waitpid(-1, &status, 0);
132         ATF_REQUIRE(pid > 0 && pid != child);
133         r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
134         ATF_CHECK_EQ(2, r);
135 }
136
137 ATF_TC(reaper_sigchld_child_first);
138 ATF_TC_HEAD(reaper_sigchld_child_first, tc)
139 {
140         atf_tc_set_md_var(tc, "timeout", "2");
141 }
142 ATF_TC_BODY(reaper_sigchld_child_first, tc)
143 {
144         struct sigaction act;
145         sigset_t mask;
146         siginfo_t info;
147         pid_t parent, child, grandchild, pid;
148         int r;
149         int pip[2];
150
151         /* Be paranoid. */
152         pid = waitpid(-1, NULL, WNOHANG);
153         ATF_REQUIRE(pid == -1 && errno == ECHILD);
154
155         act.sa_sigaction = dummy_sighandler;
156         act.sa_flags = SA_SIGINFO | SA_RESTART;
157         r = sigemptyset(&act.sa_mask);
158         ATF_REQUIRE_EQ(0, r);
159         r = sigaction(SIGCHLD, &act, NULL);
160         ATF_REQUIRE_EQ(0, r);
161
162         r = sigemptyset(&mask);
163         ATF_REQUIRE_EQ(0, r);
164         r = sigaddset(&mask, SIGCHLD);
165         ATF_REQUIRE_EQ(0, r);
166         r = sigprocmask(SIG_BLOCK, &mask, NULL);
167         ATF_REQUIRE_EQ(0, r);
168
169         parent = getpid();
170         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
171         ATF_REQUIRE_EQ(0, r);
172
173         r = pipe(pip);
174         ATF_REQUIRE_EQ(0, r);
175
176         child = fork();
177         ATF_REQUIRE(child != -1);
178         if (child == 0) {
179                 if (close(pip[1]) != 0)
180                         _exit(100);
181                 grandchild = fork();
182                 if (grandchild == -1)
183                         _exit(101);
184                 else if (grandchild == 0) {
185                         if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
186                                 _exit(102);
187                         if (getppid() != parent)
188                                 _exit(103);
189                         _exit(2);
190                 } else
191                         _exit(3);
192         }
193
194         r = sigwaitinfo(&mask, &info);
195         ATF_REQUIRE_EQ(SIGCHLD, r);
196         ATF_CHECK_EQ(SIGCHLD, info.si_signo);
197         ATF_CHECK_EQ(CLD_EXITED, info.si_code);
198         ATF_CHECK_EQ(3, info.si_status);
199         ATF_CHECK_EQ(child, info.si_pid);
200
201         pid = waitpid(child, NULL, 0);
202         ATF_REQUIRE_EQ(child, pid);
203
204         r = close(pip[1]);
205         ATF_REQUIRE_EQ(0, r);
206
207         r = sigwaitinfo(&mask, &info);
208         ATF_REQUIRE_EQ(SIGCHLD, r);
209         ATF_CHECK_EQ(SIGCHLD, info.si_signo);
210         ATF_CHECK_EQ(CLD_EXITED, info.si_code);
211         ATF_CHECK_EQ(2, info.si_status);
212         grandchild = info.si_pid;
213         ATF_REQUIRE(grandchild > 0);
214         ATF_REQUIRE(grandchild != parent);
215         ATF_REQUIRE(grandchild != child);
216
217         pid = waitpid(-1, NULL, 0);
218         ATF_REQUIRE_EQ(grandchild, pid);
219
220         r = close(pip[0]);
221         ATF_REQUIRE_EQ(0, r);
222 }
223
224 ATF_TC(reaper_sigchld_grandchild_first);
225 ATF_TC_HEAD(reaper_sigchld_grandchild_first, tc)
226 {
227         atf_tc_set_md_var(tc, "timeout", "2");
228 }
229 ATF_TC_BODY(reaper_sigchld_grandchild_first, tc)
230 {
231         struct sigaction act;
232         sigset_t mask;
233         siginfo_t info;
234         pid_t parent, child, grandchild, pid;
235         int r;
236
237         /* Be paranoid. */
238         pid = waitpid(-1, NULL, WNOHANG);
239         ATF_REQUIRE(pid == -1 && errno == ECHILD);
240
241         act.sa_sigaction = dummy_sighandler;
242         act.sa_flags = SA_SIGINFO | SA_RESTART;
243         r = sigemptyset(&act.sa_mask);
244         ATF_REQUIRE_EQ(0, r);
245         r = sigaction(SIGCHLD, &act, NULL);
246         ATF_REQUIRE_EQ(0, r);
247
248         r = sigemptyset(&mask);
249         ATF_REQUIRE_EQ(0, r);
250         r = sigaddset(&mask, SIGCHLD);
251         ATF_REQUIRE_EQ(0, r);
252         r = sigprocmask(SIG_BLOCK, &mask, NULL);
253         ATF_REQUIRE_EQ(0, r);
254
255         parent = getpid();
256         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
257         ATF_REQUIRE_EQ(0, r);
258
259         child = fork();
260         ATF_REQUIRE(child != -1);
261         if (child == 0) {
262                 grandchild = fork();
263                 if (grandchild == -1)
264                         _exit(101);
265                 else if (grandchild == 0)
266                         _exit(2);
267                 else {
268                         if (waitid(P_PID, grandchild, NULL,
269                             WNOWAIT | WEXITED) != 0)
270                                 _exit(102);
271                         _exit(3);
272                 }
273         }
274
275         pid = waitpid(child, NULL, 0);
276         ATF_REQUIRE_EQ(child, pid);
277
278         r = sigwaitinfo(&mask, &info);
279         ATF_REQUIRE_EQ(SIGCHLD, r);
280         ATF_CHECK_EQ(SIGCHLD, info.si_signo);
281         ATF_CHECK_EQ(CLD_EXITED, info.si_code);
282         ATF_CHECK_EQ(2, info.si_status);
283         grandchild = info.si_pid;
284         ATF_REQUIRE(grandchild > 0);
285         ATF_REQUIRE(grandchild != parent);
286         ATF_REQUIRE(grandchild != child);
287
288         pid = waitpid(-1, NULL, 0);
289         ATF_REQUIRE_EQ(grandchild, pid);
290 }
291
292 ATF_TC_WITHOUT_HEAD(reaper_status);
293 ATF_TC_BODY(reaper_status, tc)
294 {
295         struct procctl_reaper_status st;
296         ssize_t sr;
297         pid_t parent, child, pid;
298         int r, status;
299         int pip[2];
300
301         parent = getpid();
302         r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
303         ATF_REQUIRE_EQ(0, r);
304         ATF_CHECK_EQ(0, st.rs_flags & REAPER_STATUS_OWNED);
305         ATF_CHECK(st.rs_children > 0);
306         ATF_CHECK(st.rs_descendants > 0);
307         ATF_CHECK(st.rs_descendants >= st.rs_children);
308         ATF_CHECK(st.rs_reaper != parent);
309         ATF_CHECK(st.rs_reaper > 0);
310
311         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
312         ATF_REQUIRE_EQ(0, r);
313
314         r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
315         ATF_REQUIRE_EQ(0, r);
316         ATF_CHECK_EQ(REAPER_STATUS_OWNED,
317             st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
318         ATF_CHECK_EQ(0, st.rs_children);
319         ATF_CHECK_EQ(0, st.rs_descendants);
320         ATF_CHECK(st.rs_reaper == parent);
321         ATF_CHECK_EQ(-1, st.rs_pid);
322
323         r = pipe(pip);
324         ATF_REQUIRE_EQ(0, r);
325         child = fork();
326         ATF_REQUIRE(child != -1);
327         if (child == 0) {
328                 if (close(pip[0]) != 0)
329                         _exit(100);
330                 if (procctl(P_PID, parent, PROC_REAP_STATUS, &st) != 0)
331                         _exit(101);
332                 if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
333                         _exit(102);
334                 if (procctl(P_PID, getpid(), PROC_REAP_STATUS, &st) != 0)
335                         _exit(103);
336                 if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
337                         _exit(104);
338                 _exit(0);
339         }
340         r = close(pip[1]);
341         ATF_REQUIRE_EQ(0, r);
342
343         sr = read(pip[0], &st, sizeof(st));
344         ATF_REQUIRE_EQ((ssize_t)sizeof(st), sr);
345         ATF_CHECK_EQ(REAPER_STATUS_OWNED,
346             st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
347         ATF_CHECK_EQ(1, st.rs_children);
348         ATF_CHECK_EQ(1, st.rs_descendants);
349         ATF_CHECK(st.rs_reaper == parent);
350         ATF_CHECK_EQ(child, st.rs_pid);
351         sr = read(pip[0], &st, sizeof(st));
352         ATF_REQUIRE_EQ((ssize_t)sizeof(st), sr);
353         ATF_CHECK_EQ(0,
354             st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
355         ATF_CHECK_EQ(1, st.rs_children);
356         ATF_CHECK_EQ(1, st.rs_descendants);
357         ATF_CHECK(st.rs_reaper == parent);
358         ATF_CHECK_EQ(child, st.rs_pid);
359
360         r = close(pip[0]);
361         ATF_REQUIRE_EQ(0, r);
362         pid = waitpid(child, &status, 0);
363         ATF_REQUIRE_EQ(child, pid);
364         ATF_CHECK_EQ(0, status);
365
366         r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
367         ATF_REQUIRE_EQ(0, r);
368         ATF_CHECK_EQ(REAPER_STATUS_OWNED,
369             st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
370         ATF_CHECK_EQ(0, st.rs_children);
371         ATF_CHECK_EQ(0, st.rs_descendants);
372         ATF_CHECK(st.rs_reaper == parent);
373         ATF_CHECK_EQ(-1, st.rs_pid);
374 }
375
376 ATF_TC_WITHOUT_HEAD(reaper_getpids);
377 ATF_TC_BODY(reaper_getpids, tc)
378 {
379         struct procctl_reaper_pidinfo info[10];
380         ssize_t sr;
381         pid_t parent, child, grandchild, pid;
382         int r, status, childidx;
383         int pipa[2], pipb[2];
384
385         parent = getpid();
386         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
387         ATF_REQUIRE_EQ(0, r);
388
389         memset(info, '\0', sizeof(info));
390         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
391             &(struct procctl_reaper_pids){
392             .rp_count = sizeof(info) / sizeof(info[0]),
393             .rp_pids = info
394             });
395         ATF_CHECK_EQ(0, r);
396         ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
397
398         r = pipe(pipa);
399         ATF_REQUIRE_EQ(0, r);
400         r = pipe(pipb);
401         ATF_REQUIRE_EQ(0, r);
402         child = fork();
403         ATF_REQUIRE(child != -1);
404         if (child == 0) {
405                 if (close(pipa[1]) != 0)
406                         _exit(100);
407                 if (close(pipb[0]) != 0)
408                         _exit(100);
409                 if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
410                         _exit(101);
411                 grandchild = fork();
412                 if (grandchild == -1)
413                         _exit(102);
414                 if (grandchild == 0) {
415                         if (write(pipb[1], &(uint8_t){ 0 }, 1) != 1)
416                                 _exit(103);
417                         if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
418                                 _exit(104);
419                         _exit(0);
420                 }
421                 for (;;)
422                         pause();
423         }
424         r = close(pipa[0]);
425         ATF_REQUIRE_EQ(0, r);
426         r = close(pipb[1]);
427         ATF_REQUIRE_EQ(0, r);
428
429         memset(info, '\0', sizeof(info));
430         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
431             &(struct procctl_reaper_pids){
432             .rp_count = sizeof(info) / sizeof(info[0]),
433             .rp_pids = info
434             });
435         ATF_CHECK_EQ(0, r);
436         ATF_CHECK_EQ(REAPER_PIDINFO_VALID | REAPER_PIDINFO_CHILD,
437             info[0].pi_flags & (REAPER_PIDINFO_VALID | REAPER_PIDINFO_CHILD));
438         ATF_CHECK_EQ(child, info[0].pi_pid);
439         ATF_CHECK_EQ(child, info[0].pi_subtree);
440         ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
441
442         sr = write(pipa[1], &(uint8_t){ 0 }, 1);
443         ATF_REQUIRE_EQ(1, sr);
444         sr = read(pipb[0], &(uint8_t){ 0 }, 1);
445         ATF_REQUIRE_EQ(1, sr);
446
447         memset(info, '\0', sizeof(info));
448         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
449             &(struct procctl_reaper_pids){
450             .rp_count = sizeof(info) / sizeof(info[0]),
451             .rp_pids = info
452             });
453         ATF_CHECK_EQ(0, r);
454         ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
455             info[0].pi_flags & REAPER_PIDINFO_VALID);
456         ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
457             info[1].pi_flags & REAPER_PIDINFO_VALID);
458         ATF_CHECK_EQ(0, info[2].pi_flags & REAPER_PIDINFO_VALID);
459         ATF_CHECK_EQ(child, info[0].pi_subtree);
460         ATF_CHECK_EQ(child, info[1].pi_subtree);
461         childidx = info[1].pi_pid == child ? 1 : 0;
462         ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
463             info[childidx].pi_flags & REAPER_PIDINFO_CHILD);
464         ATF_CHECK_EQ(0, info[childidx ^ 1].pi_flags & REAPER_PIDINFO_CHILD);
465         ATF_CHECK(info[childidx].pi_pid == child);
466         grandchild = info[childidx ^ 1].pi_pid;
467         ATF_CHECK(grandchild > 0);
468         ATF_CHECK(grandchild != child);
469         ATF_CHECK(grandchild != parent);
470
471         r = kill(child, SIGTERM);
472         ATF_REQUIRE_EQ(0, r);
473
474         pid = waitpid(child, &status, 0);
475         ATF_REQUIRE_EQ(child, pid);
476         ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
477
478         memset(info, '\0', sizeof(info));
479         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
480             &(struct procctl_reaper_pids){
481             .rp_count = sizeof(info) / sizeof(info[0]),
482             .rp_pids = info
483             });
484         ATF_CHECK_EQ(0, r);
485         ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
486             info[0].pi_flags & REAPER_PIDINFO_VALID);
487         ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
488         ATF_CHECK_EQ(child, info[0].pi_subtree);
489         ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
490             info[0].pi_flags & REAPER_PIDINFO_CHILD);
491         ATF_CHECK_EQ(grandchild, info[0].pi_pid);
492
493         sr = write(pipa[1], &(uint8_t){ 0 }, 1);
494         ATF_REQUIRE_EQ(1, sr);
495
496         memset(info, '\0', sizeof(info));
497         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
498             &(struct procctl_reaper_pids){
499             .rp_count = sizeof(info) / sizeof(info[0]),
500             .rp_pids = info
501             });
502         ATF_CHECK_EQ(0, r);
503         ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
504             info[0].pi_flags & REAPER_PIDINFO_VALID);
505         ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
506         ATF_CHECK_EQ(child, info[0].pi_subtree);
507         ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
508             info[0].pi_flags & REAPER_PIDINFO_CHILD);
509         ATF_CHECK_EQ(grandchild, info[0].pi_pid);
510
511         pid = waitpid(grandchild, &status, 0);
512         ATF_REQUIRE_EQ(grandchild, pid);
513         ATF_CHECK_EQ(0, status);
514
515         memset(info, '\0', sizeof(info));
516         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
517             &(struct procctl_reaper_pids){
518             .rp_count = sizeof(info) / sizeof(info[0]),
519             .rp_pids = info
520             });
521         ATF_CHECK_EQ(0, r);
522         ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
523
524         r = close(pipa[1]);
525         ATF_REQUIRE_EQ(0, r);
526         r = close(pipb[0]);
527         ATF_REQUIRE_EQ(0, r);
528 }
529
530 ATF_TC_WITHOUT_HEAD(reaper_kill_badsig);
531 ATF_TC_BODY(reaper_kill_badsig, tc)
532 {
533         struct procctl_reaper_kill params;
534         pid_t parent;
535         int r;
536
537         parent = getpid();
538         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
539         ATF_REQUIRE_EQ(0, r);
540
541         params.rk_sig = -1;
542         params.rk_flags = 0;
543         r = procctl(P_PID, parent, PROC_REAP_KILL, &params);
544         ATF_CHECK(r == -1 && errno == EINVAL);
545 }
546
547 ATF_TC_WITHOUT_HEAD(reaper_kill_sigzero);
548 ATF_TC_BODY(reaper_kill_sigzero, tc)
549 {
550         struct procctl_reaper_kill params;
551         pid_t parent;
552         int r;
553
554         parent = getpid();
555         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
556         ATF_REQUIRE_EQ(0, r);
557
558         params.rk_sig = 0;
559         params.rk_flags = 0;
560         r = procctl(P_PID, parent, PROC_REAP_KILL, &params);
561         ATF_CHECK(r == -1 && errno == EINVAL);
562 }
563
564 ATF_TC_WITHOUT_HEAD(reaper_kill_empty);
565 ATF_TC_BODY(reaper_kill_empty, tc)
566 {
567         struct procctl_reaper_kill params;
568         pid_t parent;
569         int r;
570
571         parent = getpid();
572         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
573         ATF_REQUIRE_EQ(0, r);
574
575         params.rk_sig = SIGTERM;
576         params.rk_flags = 0;
577         params.rk_killed = 77;
578         r = procctl(P_PID, parent, PROC_REAP_KILL, &params);
579         ATF_CHECK(r == -1 && errno == ESRCH);
580         ATF_CHECK_EQ(0, params.rk_killed);
581 }
582
583 ATF_TC_WITHOUT_HEAD(reaper_kill_normal);
584 ATF_TC_BODY(reaper_kill_normal, tc)
585 {
586         struct procctl_reaper_kill params;
587         ssize_t sr;
588         pid_t parent, child, grandchild, pid;
589         int r, status;
590         int pip[2];
591
592         parent = getpid();
593         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
594         ATF_REQUIRE_EQ(0, r);
595
596         r = pipe(pip);
597         ATF_REQUIRE_EQ(0, r);
598         child = fork();
599         ATF_REQUIRE(child != -1);
600         if (child == 0) {
601                 if (close(pip[0]) != 0)
602                         _exit(100);
603                 grandchild = fork();
604                 if (grandchild == -1)
605                         _exit(101);
606                 if (grandchild == 0) {
607                         if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
608                                 _exit(102);
609                         for (;;)
610                                 pause();
611                 }
612                 for (;;)
613                         pause();
614         }
615         r = close(pip[1]);
616         ATF_REQUIRE_EQ(0, r);
617
618         sr = read(pip[0], &(uint8_t){ 0 }, 1);
619         ATF_REQUIRE_EQ(1, sr);
620
621         params.rk_sig = SIGTERM;
622         params.rk_flags = 0;
623         params.rk_killed = 77;
624         r = procctl(P_PID, parent, PROC_REAP_KILL, &params);
625         ATF_CHECK_EQ(0, r);
626         ATF_CHECK_EQ(2, params.rk_killed);
627
628         pid = waitpid(child, &status, 0);
629         ATF_REQUIRE_EQ(child, pid);
630         ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
631
632         pid = waitpid(-1, &status, 0);
633         ATF_REQUIRE(pid > 0);
634         ATF_CHECK(pid != parent);
635         ATF_CHECK(pid != child);
636         ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
637
638         r = close(pip[0]);
639         ATF_REQUIRE_EQ(0, r);
640 }
641
642 ATF_TP_ADD_TCS(tp)
643 {
644
645         ATF_TP_ADD_TC(tp, reaper_wait_child_first);
646         ATF_TP_ADD_TC(tp, reaper_wait_grandchild_first);
647         ATF_TP_ADD_TC(tp, reaper_sigchld_child_first);
648         ATF_TP_ADD_TC(tp, reaper_sigchld_grandchild_first);
649         ATF_TP_ADD_TC(tp, reaper_status);
650         ATF_TP_ADD_TC(tp, reaper_getpids);
651         ATF_TP_ADD_TC(tp, reaper_kill_badsig);
652         ATF_TP_ADD_TC(tp, reaper_kill_sigzero);
653         ATF_TP_ADD_TC(tp, reaper_kill_empty);
654         ATF_TP_ADD_TC(tp, reaper_kill_normal);
655         return (atf_no_error());
656 }