1 /*
2  * Copyright (c) International Business Machines  Corp., 2001
3  *
4  * This program is free software;  you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12  * the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.
16  *
17  * History
18  *	07/2001 John George
19  *		-Ported
20  *      04/2002 wjhuie sigset cleanups
21  */
22 
23 /*
24  * case 0:
25  *        waitpid(pid, WNOHANG) should return 0 if there is a running child
26  * case 1:
27  *        waitpid(pid, WNOHANG) should return the pid of the child if
28  *        the child has exited
29  * case 2:
30  *        waitpid(-1, 0) should return -1 with ECHILD if
31  *        there are no children to wait for.
32  * case 3:
33  *        waitpid(-1, WNOHANG) should return -1 with ECHILD if
34  *        there are no children to wait for.
35  */
36 
37 #define _GNU_SOURCE 1
38 #include <sys/types.h>
39 #include <signal.h>
40 #include <errno.h>
41 #include <sys/wait.h>
42 #include <stdlib.h>
43 #include "tst_test.h"
44 
45 static void cleanup_pid(pid_t pid)
46 {
47 	if (pid > 0) {
48 		kill(pid, SIGKILL);
49 		waitpid(pid, NULL, 0);
50 	}
51 }
52 
53 static void case0(void)
54 {
55 	pid_t pid, ret;
56 	int status;
57 
58 	pid = SAFE_FORK();
59 	if (pid == 0) {
60 		TST_CHECKPOINT_WAIT(0);
61 
62 		exit(0);
63 	}
64 
65 	for (;;) {
66 		ret = waitpid(pid, &status, WNOHANG);
67 
68 		if ((ret == -1) && (errno == EINTR))
69 			continue;
70 
71 		if (ret == 0)
72 			break;
73 
74 		tst_res(TFAIL, "waitpid(WNOHANG) returned %d, expected 0",
75 			ret);
76 		cleanup_pid(pid);
77 		return;
78 	}
79 
80 	TST_CHECKPOINT_WAKE(0);
81 	SAFE_WAITPID(pid, NULL, 0);
82 
83 	tst_res(TPASS, "waitpid(pid, WNOHANG) = 0 for a running child");
84 }
85 
86 static void case1(void)
87 {
88 	pid_t pid, ret;
89 	int status;
90 
91 	pid = SAFE_FORK();
92 	if (pid == 0)
93 		exit(0);
94 
95 	for (;;) {
96 		ret = waitpid(pid, &status, WNOHANG);
97 
98 		if ((ret == -1) && (errno == EINTR))
99 			continue;
100 		if (ret == 0)
101 			continue;
102 
103 		if (ret == pid)
104 			break;
105 
106 		tst_res(TFAIL, "waitpid(WNOHANG) returned %d, expected %d",
107 			ret, pid);
108 		cleanup_pid(pid);
109 		return;
110 	}
111 
112 	if (!WIFEXITED(status)) {
113 		tst_res(TFAIL, "Child exited abnormally");
114 		return;
115 	}
116 
117 	if (WEXITSTATUS(status) != 0) {
118 		tst_res(TFAIL, "Child exited with %d, expected 0",
119 			WEXITSTATUS(status));
120 		return;
121 	}
122 
123 	tst_res(TPASS, "waitpid(pid, WNOHANG) = pid for an exited child");
124 }
125 
126 static void case2(void)
127 {
128 	pid_t ret;
129 	int status;
130 
131 	ret = waitpid(-1, &status, 0);
132 
133 	if (ret != -1) {
134 		tst_res(TFAIL, "Expected -1, got %d", ret);
135 		return;
136 	}
137 	if (errno != ECHILD) {
138 		tst_res(TFAIL, "Expected %s, got %s",
139 			tst_strerrno(ECHILD), tst_strerrno(errno));
140 		return;
141 	}
142 
143 	tst_res(TPASS, "waitpid(-1, 0) = -1 with ECHILD if no children");
144 }
145 
146 static void case3(void)
147 {
148 	pid_t ret;
149 	int status;
150 
151 	ret = waitpid(-1, &status, WNOHANG);
152 	if (ret != -1) {
153 		tst_res(TFAIL, "WNOHANG: Expected -1, got %d", ret);
154 		return;
155 	}
156 	if (errno != ECHILD) {
157 		tst_res(TFAIL, "WNOHANG: Expected %s, got %s",
158 			tst_strerrno(ECHILD), tst_strerrno(errno));
159 		return;
160 	}
161 
162 	tst_res(TPASS, "waitpid(-1, WNOHANG) = -1 with ECHILD if no children");
163 }
164 
165 static void (*tests[])(void) = { case0, case1, case2, case3 };
166 
167 static void waitpid09_test(unsigned int id)
168 {
169 	tests[id]();
170 }
171 
172 static struct tst_test test = {
173 	.forks_child = 1,
174 	.needs_checkpoints = 1,
175 	.test = waitpid09_test,
176 	.tcnt = ARRAY_SIZE(tests),
177 };
178