xref: /linux/tools/testing/selftests/pidfd/pidfd_wait.c (revision f96a974170b749e3a56844e25b31d46a7233b6f6)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <linux/sched.h>
6 #include <linux/types.h>
7 #include <signal.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sched.h>
12 #include <string.h>
13 #include <sys/resource.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17 #include <unistd.h>
18 
19 #include "pidfd.h"
20 #include "../kselftest_harness.h"
21 
22 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
23 
24 /* Attempt to de-conflict with the selftests tree. */
25 #ifndef SKIP
26 #define SKIP(s, ...)	XFAIL(s, ##__VA_ARGS__)
27 #endif
28 
29 TEST(wait_simple)
30 {
31 	int pidfd = -1;
32 	pid_t parent_tid = -1;
33 	struct __clone_args args = {
34 		.parent_tid = ptr_to_u64(&parent_tid),
35 		.pidfd = ptr_to_u64(&pidfd),
36 		.flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
37 		.exit_signal = SIGCHLD,
38 	};
39 	pid_t pid;
40 	siginfo_t info = {
41 		.si_signo = 0,
42 	};
43 
44 	pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
45 	ASSERT_GE(pidfd, 0);
46 
47 	pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
48 	ASSERT_NE(pid, 0);
49 	EXPECT_EQ(close(pidfd), 0);
50 	pidfd = -1;
51 
52 	pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
53 	ASSERT_GE(pidfd, 0);
54 
55 	pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
56 	ASSERT_NE(pid, 0);
57 	EXPECT_EQ(close(pidfd), 0);
58 	pidfd = -1;
59 
60 	pid = sys_clone3(&args, sizeof(args));
61 	ASSERT_GE(pid, 0);
62 
63 	if (pid == 0)
64 		exit(EXIT_SUCCESS);
65 
66 	pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
67 	ASSERT_GE(pid, 0);
68 	ASSERT_EQ(WIFEXITED(info.si_status), true);
69 	ASSERT_EQ(WEXITSTATUS(info.si_status), 0);
70 	EXPECT_EQ(close(pidfd), 0);
71 
72 	ASSERT_EQ(info.si_signo, SIGCHLD);
73 	ASSERT_EQ(info.si_code, CLD_EXITED);
74 	ASSERT_EQ(info.si_pid, parent_tid);
75 }
76 
77 TEST(wait_states)
78 {
79 	int pidfd = -1;
80 	pid_t parent_tid = -1;
81 	struct __clone_args args = {
82 		.parent_tid = ptr_to_u64(&parent_tid),
83 		.pidfd = ptr_to_u64(&pidfd),
84 		.flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
85 		.exit_signal = SIGCHLD,
86 	};
87 	int pfd[2];
88 	pid_t pid;
89 	siginfo_t info = {
90 		.si_signo = 0,
91 	};
92 
93 	ASSERT_EQ(pipe(pfd), 0);
94 	pid = sys_clone3(&args, sizeof(args));
95 	ASSERT_GE(pid, 0);
96 
97 	if (pid == 0) {
98 		char buf[2];
99 
100 		close(pfd[1]);
101 		kill(getpid(), SIGSTOP);
102 		ASSERT_EQ(read(pfd[0], buf, 1), 1);
103 		close(pfd[0]);
104 		kill(getpid(), SIGSTOP);
105 		exit(EXIT_SUCCESS);
106 	}
107 
108 	close(pfd[0]);
109 	ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED), 0);
110 	ASSERT_EQ(info.si_signo, SIGCHLD);
111 	ASSERT_EQ(info.si_code, CLD_STOPPED);
112 	ASSERT_EQ(info.si_pid, parent_tid);
113 
114 	ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
115 
116 	ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED), 0);
117 	ASSERT_EQ(write(pfd[1], "C", 1), 1);
118 	close(pfd[1]);
119 	ASSERT_EQ(info.si_signo, SIGCHLD);
120 	ASSERT_EQ(info.si_code, CLD_CONTINUED);
121 	ASSERT_EQ(info.si_pid, parent_tid);
122 
123 	ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED), 0);
124 	ASSERT_EQ(info.si_signo, SIGCHLD);
125 	ASSERT_EQ(info.si_code, CLD_STOPPED);
126 	ASSERT_EQ(info.si_pid, parent_tid);
127 
128 	ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0);
129 
130 	ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED), 0);
131 	ASSERT_EQ(info.si_signo, SIGCHLD);
132 	ASSERT_EQ(info.si_code, CLD_KILLED);
133 	ASSERT_EQ(info.si_pid, parent_tid);
134 
135 	EXPECT_EQ(close(pidfd), 0);
136 }
137 
138 TEST(wait_nonblock)
139 {
140 	int pidfd;
141 	unsigned int flags = 0;
142 	pid_t parent_tid = -1;
143 	struct __clone_args args = {
144 		.parent_tid = ptr_to_u64(&parent_tid),
145 		.flags = CLONE_PARENT_SETTID,
146 		.exit_signal = SIGCHLD,
147 	};
148 	int ret;
149 	pid_t pid;
150 	siginfo_t info = {
151 		.si_signo = 0,
152 	};
153 
154 	/*
155 	 * Callers need to see ECHILD with non-blocking pidfds when no child
156 	 * processes exists.
157 	 */
158 	pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK);
159 	EXPECT_GE(pidfd, 0) {
160 		/* pidfd_open() doesn't support PIDFD_NONBLOCK. */
161 		ASSERT_EQ(errno, EINVAL);
162 		SKIP(return, "Skipping PIDFD_NONBLOCK test");
163 	}
164 
165 	ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
166 	ASSERT_LT(ret, 0);
167 	ASSERT_EQ(errno, ECHILD);
168 	EXPECT_EQ(close(pidfd), 0);
169 
170 	pid = sys_clone3(&args, sizeof(args));
171 	ASSERT_GE(pid, 0);
172 
173 	if (pid == 0) {
174 		kill(getpid(), SIGSTOP);
175 		exit(EXIT_SUCCESS);
176 	}
177 
178 	pidfd = sys_pidfd_open(pid, PIDFD_NONBLOCK);
179 	EXPECT_GE(pidfd, 0) {
180 		/* pidfd_open() doesn't support PIDFD_NONBLOCK. */
181 		ASSERT_EQ(errno, EINVAL);
182 		SKIP(return, "Skipping PIDFD_NONBLOCK test");
183 	}
184 
185 	flags = fcntl(pidfd, F_GETFL, 0);
186 	ASSERT_GT(flags, 0);
187 	ASSERT_GT((flags & O_NONBLOCK), 0);
188 
189 	/*
190 	 * Callers need to see EAGAIN/EWOULDBLOCK with non-blocking pidfd when
191 	 * child processes exist but none have exited.
192 	 */
193 	ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
194 	ASSERT_LT(ret, 0);
195 	ASSERT_EQ(errno, EAGAIN);
196 
197 	/*
198 	 * Callers need to continue seeing 0 with non-blocking pidfd and
199 	 * WNOHANG raised explicitly when child processes exist but none have
200 	 * exited.
201 	 */
202 	ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG);
203 	ASSERT_EQ(ret, 0);
204 
205 	ASSERT_EQ(fcntl(pidfd, F_SETFL, (flags & ~O_NONBLOCK)), 0);
206 
207 	ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED), 0);
208 	ASSERT_EQ(info.si_signo, SIGCHLD);
209 	ASSERT_EQ(info.si_code, CLD_STOPPED);
210 	ASSERT_EQ(info.si_pid, parent_tid);
211 
212 	ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
213 
214 	ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED), 0);
215 	ASSERT_EQ(info.si_signo, SIGCHLD);
216 	ASSERT_EQ(info.si_code, CLD_EXITED);
217 	ASSERT_EQ(info.si_pid, parent_tid);
218 
219 	EXPECT_EQ(close(pidfd), 0);
220 }
221 
222 TEST_HARNESS_MAIN
223