1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) International Business Machines Corp., 2001
4 */
5
6 /*
7 * case 0:
8 * waitpid(pid, WNOHANG) should return 0 if there is a running child
9 * case 1:
10 * waitpid(pid, WNOHANG) should return the pid of the child if
11 * the child has exited
12 * case 2:
13 * waitpid(-1, 0) should return -1 with ECHILD if
14 * there are no children to wait for.
15 * case 3:
16 * waitpid(-1, WNOHANG) should return -1 with ECHILD if
17 * there are no children to wait for.
18 */
19
20 #define _GNU_SOURCE 1
21 #include <sys/types.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include <sys/wait.h>
25 #include <stdlib.h>
26 #include "tst_test.h"
27
cleanup_pid(pid_t pid)28 static void cleanup_pid(pid_t pid)
29 {
30 if (pid > 0) {
31 kill(pid, SIGKILL);
32 waitpid(pid, NULL, 0);
33 }
34 }
35
case0(void)36 static void case0(void)
37 {
38 pid_t pid, ret;
39 int status;
40
41 pid = SAFE_FORK();
42 if (pid == 0) {
43 TST_CHECKPOINT_WAIT(0);
44
45 exit(0);
46 }
47
48 for (;;) {
49 ret = waitpid(pid, &status, WNOHANG);
50
51 if ((ret == -1) && (errno == EINTR))
52 continue;
53
54 if (ret == 0)
55 break;
56
57 tst_res(TFAIL, "waitpid(WNOHANG) returned %d, expected 0",
58 ret);
59 cleanup_pid(pid);
60 return;
61 }
62
63 TST_CHECKPOINT_WAKE(0);
64 SAFE_WAITPID(pid, NULL, 0);
65
66 tst_res(TPASS, "waitpid(pid, WNOHANG) = 0 for a running child");
67 }
68
case1(void)69 static void case1(void)
70 {
71 pid_t pid, ret;
72 int status;
73
74 pid = SAFE_FORK();
75 if (pid == 0)
76 exit(0);
77
78 for (;;) {
79 ret = waitpid(pid, &status, WNOHANG);
80
81 if ((ret == -1) && (errno == EINTR))
82 continue;
83 if (ret == 0)
84 continue;
85
86 if (ret == pid)
87 break;
88
89 tst_res(TFAIL, "waitpid(WNOHANG) returned %d, expected %d",
90 ret, pid);
91 cleanup_pid(pid);
92 return;
93 }
94
95 if (!WIFEXITED(status)) {
96 tst_res(TFAIL, "Child exited abnormally");
97 return;
98 }
99
100 if (WEXITSTATUS(status) != 0) {
101 tst_res(TFAIL, "Child exited with %d, expected 0",
102 WEXITSTATUS(status));
103 return;
104 }
105
106 tst_res(TPASS, "waitpid(pid, WNOHANG) = pid for an exited child");
107 }
108
case2(void)109 static void case2(void)
110 {
111 pid_t ret;
112 int status;
113
114 ret = waitpid(-1, &status, 0);
115
116 if (ret != -1) {
117 tst_res(TFAIL, "Expected -1, got %d", ret);
118 return;
119 }
120 if (errno != ECHILD) {
121 tst_res(TFAIL, "Expected %s, got %s",
122 tst_strerrno(ECHILD), tst_strerrno(errno));
123 return;
124 }
125
126 tst_res(TPASS, "waitpid(-1, 0) = -1 with ECHILD if no children");
127 }
128
case3(void)129 static void case3(void)
130 {
131 pid_t ret;
132 int status;
133
134 ret = waitpid(-1, &status, WNOHANG);
135 if (ret != -1) {
136 tst_res(TFAIL, "WNOHANG: Expected -1, got %d", ret);
137 return;
138 }
139 if (errno != ECHILD) {
140 tst_res(TFAIL, "WNOHANG: Expected %s, got %s",
141 tst_strerrno(ECHILD), tst_strerrno(errno));
142 return;
143 }
144
145 tst_res(TPASS, "waitpid(-1, WNOHANG) = -1 with ECHILD if no children");
146 }
147
148 static void (*tests[])(void) = { case0, case1, case2, case3 };
149
waitpid09_test(unsigned int id)150 static void waitpid09_test(unsigned int id)
151 {
152 tests[id]();
153 }
154
155 static struct tst_test test = {
156 .forks_child = 1,
157 .needs_checkpoints = 1,
158 .test = waitpid09_test,
159 .tcnt = ARRAY_SIZE(tests),
160 };
161