]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - tests/sys/kern/reaper.c
MFC r309836: Add some tests for reaper functionality (in procctl()).
[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 ATF_TC_WITHOUT_HEAD(reaper_wait_child_first);
39 ATF_TC_BODY(reaper_wait_child_first, tc)
40 {
41         pid_t parent, child, grandchild, pid;
42         int status, r;
43         int pip[2];
44
45         /* Be paranoid. */
46         pid = waitpid(-1, NULL, WNOHANG);
47         ATF_REQUIRE(pid == -1 && errno == ECHILD);
48
49         parent = getpid();
50         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
51         ATF_REQUIRE_EQ(0, r);
52
53         r = pipe(pip);
54         ATF_REQUIRE_EQ(0, r);
55
56         child = fork();
57         ATF_REQUIRE(child != -1);
58         if (child == 0) {
59                 if (close(pip[1]) != 0)
60                         _exit(100);
61                 grandchild = fork();
62                 if (grandchild == -1)
63                         _exit(101);
64                 else if (grandchild == 0) {
65                         if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
66                                 _exit(102);
67                         if (getppid() != parent)
68                                 _exit(103);
69                         _exit(2);
70                 } else
71                         _exit(3);
72         }
73
74         pid = waitpid(child, &status, 0);
75         ATF_REQUIRE_EQ(child, pid);
76         r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
77         ATF_CHECK_EQ(3, r);
78
79         r = close(pip[1]);
80         ATF_REQUIRE_EQ(0, r);
81
82         pid = waitpid(-1, &status, 0);
83         ATF_REQUIRE(pid > 0 && pid != child);
84         r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
85         ATF_CHECK_EQ(2, r);
86
87         r = close(pip[0]);
88         ATF_REQUIRE_EQ(0, r);
89 }
90
91 ATF_TC_WITHOUT_HEAD(reaper_wait_grandchild_first);
92 ATF_TC_BODY(reaper_wait_grandchild_first, tc)
93 {
94         pid_t parent, child, grandchild, pid;
95         int status, r;
96
97         /* Be paranoid. */
98         pid = waitpid(-1, NULL, WNOHANG);
99         ATF_REQUIRE(pid == -1 && errno == ECHILD);
100
101         parent = getpid();
102         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
103         ATF_REQUIRE_EQ(0, r);
104
105         child = fork();
106         ATF_REQUIRE(child != -1);
107         if (child == 0) {
108                 grandchild = fork();
109                 if (grandchild == -1)
110                         _exit(101);
111                 else if (grandchild == 0)
112                         _exit(2);
113                 else {
114                         if (waitid(P_PID, grandchild, NULL,
115                             WNOWAIT | WEXITED) != 0)
116                                 _exit(102);
117                         _exit(3);
118                 }
119         }
120
121         pid = waitpid(child, &status, 0);
122         ATF_REQUIRE_EQ(child, pid);
123         r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
124         ATF_CHECK_EQ(3, r);
125
126         pid = waitpid(-1, &status, 0);
127         ATF_REQUIRE(pid > 0 && pid != child);
128         r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
129         ATF_CHECK_EQ(2, r);
130 }
131
132 ATF_TC_WITHOUT_HEAD(reaper_status);
133 ATF_TC_BODY(reaper_status, tc)
134 {
135         struct procctl_reaper_status st;
136         ssize_t sr;
137         pid_t parent, child, pid;
138         int r, status;
139         int pip[2];
140
141         parent = getpid();
142         r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
143         ATF_REQUIRE_EQ(0, r);
144         ATF_CHECK_EQ(0, st.rs_flags & REAPER_STATUS_OWNED);
145         ATF_CHECK(st.rs_children > 0);
146         ATF_CHECK(st.rs_descendants > 0);
147         ATF_CHECK(st.rs_descendants >= st.rs_children);
148         ATF_CHECK(st.rs_reaper != parent);
149         ATF_CHECK(st.rs_reaper > 0);
150
151         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
152         ATF_REQUIRE_EQ(0, r);
153
154         r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
155         ATF_REQUIRE_EQ(0, r);
156         ATF_CHECK_EQ(REAPER_STATUS_OWNED,
157             st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
158         ATF_CHECK_EQ(0, st.rs_children);
159         ATF_CHECK_EQ(0, st.rs_descendants);
160         ATF_CHECK(st.rs_reaper == parent);
161         ATF_CHECK_EQ(-1, st.rs_pid);
162
163         r = pipe(pip);
164         ATF_REQUIRE_EQ(0, r);
165         child = fork();
166         ATF_REQUIRE(child != -1);
167         if (child == 0) {
168                 if (close(pip[0]) != 0)
169                         _exit(100);
170                 if (procctl(P_PID, parent, PROC_REAP_STATUS, &st) != 0)
171                         _exit(101);
172                 if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
173                         _exit(102);
174                 if (procctl(P_PID, getpid(), PROC_REAP_STATUS, &st) != 0)
175                         _exit(103);
176                 if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
177                         _exit(104);
178                 _exit(0);
179         }
180         r = close(pip[1]);
181         ATF_REQUIRE_EQ(0, r);
182
183         sr = read(pip[0], &st, sizeof(st));
184         ATF_REQUIRE_EQ((ssize_t)sizeof(st), sr);
185         ATF_CHECK_EQ(REAPER_STATUS_OWNED,
186             st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
187         ATF_CHECK_EQ(1, st.rs_children);
188         ATF_CHECK_EQ(1, st.rs_descendants);
189         ATF_CHECK(st.rs_reaper == parent);
190         ATF_CHECK_EQ(child, st.rs_pid);
191         sr = read(pip[0], &st, sizeof(st));
192         ATF_REQUIRE_EQ((ssize_t)sizeof(st), sr);
193         ATF_CHECK_EQ(0,
194             st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
195         ATF_CHECK_EQ(1, st.rs_children);
196         ATF_CHECK_EQ(1, st.rs_descendants);
197         ATF_CHECK(st.rs_reaper == parent);
198         ATF_CHECK_EQ(child, st.rs_pid);
199
200         r = close(pip[0]);
201         ATF_REQUIRE_EQ(0, r);
202         pid = waitpid(child, &status, 0);
203         ATF_REQUIRE_EQ(child, pid);
204         ATF_CHECK_EQ(0, status);
205
206         r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
207         ATF_REQUIRE_EQ(0, r);
208         ATF_CHECK_EQ(REAPER_STATUS_OWNED,
209             st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
210         ATF_CHECK_EQ(0, st.rs_children);
211         ATF_CHECK_EQ(0, st.rs_descendants);
212         ATF_CHECK(st.rs_reaper == parent);
213         ATF_CHECK_EQ(-1, st.rs_pid);
214 }
215
216 ATF_TC_WITHOUT_HEAD(reaper_getpids);
217 ATF_TC_BODY(reaper_getpids, tc)
218 {
219         struct procctl_reaper_pidinfo info[10];
220         ssize_t sr;
221         pid_t parent, child, grandchild, pid;
222         int r, status, childidx;
223         int pipa[2], pipb[2];
224
225         parent = getpid();
226         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
227         ATF_REQUIRE_EQ(0, r);
228
229         memset(info, '\0', sizeof(info));
230         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
231             &(struct procctl_reaper_pids){
232             .rp_count = sizeof(info) / sizeof(info[0]),
233             .rp_pids = info
234             });
235         ATF_CHECK_EQ(0, r);
236         ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
237
238         r = pipe(pipa);
239         ATF_REQUIRE_EQ(0, r);
240         r = pipe(pipb);
241         ATF_REQUIRE_EQ(0, r);
242         child = fork();
243         ATF_REQUIRE(child != -1);
244         if (child == 0) {
245                 if (close(pipa[1]) != 0)
246                         _exit(100);
247                 if (close(pipb[0]) != 0)
248                         _exit(100);
249                 if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
250                         _exit(101);
251                 grandchild = fork();
252                 if (grandchild == -1)
253                         _exit(102);
254                 if (grandchild == 0) {
255                         if (write(pipb[1], &(uint8_t){ 0 }, 1) != 1)
256                                 _exit(103);
257                         if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
258                                 _exit(104);
259                         _exit(0);
260                 }
261                 for (;;)
262                         pause();
263         }
264         r = close(pipa[0]);
265         ATF_REQUIRE_EQ(0, r);
266         r = close(pipb[1]);
267         ATF_REQUIRE_EQ(0, r);
268
269         memset(info, '\0', sizeof(info));
270         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
271             &(struct procctl_reaper_pids){
272             .rp_count = sizeof(info) / sizeof(info[0]),
273             .rp_pids = info
274             });
275         ATF_CHECK_EQ(0, r);
276         ATF_CHECK_EQ(REAPER_PIDINFO_VALID | REAPER_PIDINFO_CHILD,
277             info[0].pi_flags & (REAPER_PIDINFO_VALID | REAPER_PIDINFO_CHILD));
278         ATF_CHECK_EQ(child, info[0].pi_pid);
279         ATF_CHECK_EQ(child, info[0].pi_subtree);
280         ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
281
282         sr = write(pipa[1], &(uint8_t){ 0 }, 1);
283         ATF_REQUIRE_EQ(1, sr);
284         sr = read(pipb[0], &(uint8_t){ 0 }, 1);
285         ATF_REQUIRE_EQ(1, sr);
286
287         memset(info, '\0', sizeof(info));
288         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
289             &(struct procctl_reaper_pids){
290             .rp_count = sizeof(info) / sizeof(info[0]),
291             .rp_pids = info
292             });
293         ATF_CHECK_EQ(0, r);
294         ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
295             info[0].pi_flags & REAPER_PIDINFO_VALID);
296         ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
297             info[1].pi_flags & REAPER_PIDINFO_VALID);
298         ATF_CHECK_EQ(0, info[2].pi_flags & REAPER_PIDINFO_VALID);
299         ATF_CHECK_EQ(child, info[0].pi_subtree);
300         ATF_CHECK_EQ(child, info[1].pi_subtree);
301         childidx = info[1].pi_pid == child ? 1 : 0;
302         ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
303             info[childidx].pi_flags & REAPER_PIDINFO_CHILD);
304         ATF_CHECK_EQ(0, info[childidx ^ 1].pi_flags & REAPER_PIDINFO_CHILD);
305         ATF_CHECK(info[childidx].pi_pid == child);
306         grandchild = info[childidx ^ 1].pi_pid;
307         ATF_CHECK(grandchild > 0);
308         ATF_CHECK(grandchild != child);
309         ATF_CHECK(grandchild != parent);
310
311         r = kill(child, SIGTERM);
312         ATF_REQUIRE_EQ(0, r);
313
314         pid = waitpid(child, &status, 0);
315         ATF_REQUIRE_EQ(child, pid);
316         ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
317
318         memset(info, '\0', sizeof(info));
319         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
320             &(struct procctl_reaper_pids){
321             .rp_count = sizeof(info) / sizeof(info[0]),
322             .rp_pids = info
323             });
324         ATF_CHECK_EQ(0, r);
325         ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
326             info[0].pi_flags & REAPER_PIDINFO_VALID);
327         ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
328         ATF_CHECK_EQ(child, info[0].pi_subtree);
329         ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
330             info[0].pi_flags & REAPER_PIDINFO_CHILD);
331         ATF_CHECK_EQ(grandchild, info[0].pi_pid);
332
333         sr = write(pipa[1], &(uint8_t){ 0 }, 1);
334         ATF_REQUIRE_EQ(1, sr);
335
336         memset(info, '\0', sizeof(info));
337         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
338             &(struct procctl_reaper_pids){
339             .rp_count = sizeof(info) / sizeof(info[0]),
340             .rp_pids = info
341             });
342         ATF_CHECK_EQ(0, r);
343         ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
344             info[0].pi_flags & REAPER_PIDINFO_VALID);
345         ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
346         ATF_CHECK_EQ(child, info[0].pi_subtree);
347         ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
348             info[0].pi_flags & REAPER_PIDINFO_CHILD);
349         ATF_CHECK_EQ(grandchild, info[0].pi_pid);
350
351         pid = waitpid(grandchild, &status, 0);
352         ATF_REQUIRE_EQ(grandchild, pid);
353         ATF_CHECK_EQ(0, status);
354
355         memset(info, '\0', sizeof(info));
356         r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
357             &(struct procctl_reaper_pids){
358             .rp_count = sizeof(info) / sizeof(info[0]),
359             .rp_pids = info
360             });
361         ATF_CHECK_EQ(0, r);
362         ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
363
364         r = close(pipa[1]);
365         ATF_REQUIRE_EQ(0, r);
366         r = close(pipb[0]);
367         ATF_REQUIRE_EQ(0, r);
368 }
369
370 ATF_TC_WITHOUT_HEAD(reaper_kill_badsig);
371 ATF_TC_BODY(reaper_kill_badsig, tc)
372 {
373         struct procctl_reaper_kill params;
374         pid_t parent;
375         int r;
376
377         parent = getpid();
378         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
379         ATF_REQUIRE_EQ(0, r);
380
381         params.rk_sig = -1;
382         params.rk_flags = 0;
383         r = procctl(P_PID, parent, PROC_REAP_KILL, &params);
384         ATF_CHECK(r == -1 && errno == EINVAL);
385 }
386
387 ATF_TC_WITHOUT_HEAD(reaper_kill_sigzero);
388 ATF_TC_BODY(reaper_kill_sigzero, tc)
389 {
390         struct procctl_reaper_kill params;
391         pid_t parent;
392         int r;
393
394         parent = getpid();
395         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
396         ATF_REQUIRE_EQ(0, r);
397
398         params.rk_sig = 0;
399         params.rk_flags = 0;
400         r = procctl(P_PID, parent, PROC_REAP_KILL, &params);
401         ATF_CHECK(r == -1 && errno == EINVAL);
402 }
403
404 ATF_TC_WITHOUT_HEAD(reaper_kill_empty);
405 ATF_TC_BODY(reaper_kill_empty, tc)
406 {
407         struct procctl_reaper_kill params;
408         pid_t parent;
409         int r;
410
411         parent = getpid();
412         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
413         ATF_REQUIRE_EQ(0, r);
414
415         params.rk_sig = SIGTERM;
416         params.rk_flags = 0;
417         params.rk_killed = 77;
418         r = procctl(P_PID, parent, PROC_REAP_KILL, &params);
419         ATF_CHECK(r == -1 && errno == ESRCH);
420         ATF_CHECK_EQ(0, params.rk_killed);
421 }
422
423 ATF_TC_WITHOUT_HEAD(reaper_kill_normal);
424 ATF_TC_BODY(reaper_kill_normal, tc)
425 {
426         struct procctl_reaper_kill params;
427         ssize_t sr;
428         pid_t parent, child, grandchild, pid;
429         int r, status;
430         int pip[2];
431
432         parent = getpid();
433         r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
434         ATF_REQUIRE_EQ(0, r);
435
436         r = pipe(pip);
437         ATF_REQUIRE_EQ(0, r);
438         child = fork();
439         ATF_REQUIRE(child != -1);
440         if (child == 0) {
441                 if (close(pip[0]) != 0)
442                         _exit(100);
443                 grandchild = fork();
444                 if (grandchild == -1)
445                         _exit(101);
446                 if (grandchild == 0) {
447                         if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
448                                 _exit(102);
449                         for (;;)
450                                 pause();
451                 }
452                 for (;;)
453                         pause();
454         }
455         r = close(pip[1]);
456         ATF_REQUIRE_EQ(0, r);
457
458         sr = read(pip[0], &(uint8_t){ 0 }, 1);
459         ATF_REQUIRE_EQ(1, sr);
460
461         params.rk_sig = SIGTERM;
462         params.rk_flags = 0;
463         params.rk_killed = 77;
464         r = procctl(P_PID, parent, PROC_REAP_KILL, &params);
465         ATF_CHECK_EQ(0, r);
466         ATF_CHECK_EQ(2, params.rk_killed);
467
468         pid = waitpid(child, &status, 0);
469         ATF_REQUIRE_EQ(child, pid);
470         ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
471
472         pid = waitpid(-1, &status, 0);
473         ATF_REQUIRE(pid > 0);
474         ATF_CHECK(pid != parent);
475         ATF_CHECK(pid != child);
476         ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
477
478         r = close(pip[0]);
479         ATF_REQUIRE_EQ(0, r);
480 }
481
482 ATF_TP_ADD_TCS(tp)
483 {
484
485         ATF_TP_ADD_TC(tp, reaper_wait_child_first);
486         ATF_TP_ADD_TC(tp, reaper_wait_grandchild_first);
487         ATF_TP_ADD_TC(tp, reaper_status);
488         ATF_TP_ADD_TC(tp, reaper_getpids);
489         ATF_TP_ADD_TC(tp, reaper_kill_badsig);
490         ATF_TP_ADD_TC(tp, reaper_kill_sigzero);
491         ATF_TP_ADD_TC(tp, reaper_kill_empty);
492         ATF_TP_ADD_TC(tp, reaper_kill_normal);
493         return (atf_no_error());
494 }