1 /* SPDX-License-Identifier: GPL-2.0 */
5 #include <linux/sched.h>
6 #include <linux/types.h>
13 #include <sys/resource.h>
15 #include <sys/types.h>
20 #include "../kselftest_harness.h"
22 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
24 /* Attempt to de-conflict with the selftests tree. */
26 #define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__)
29 static pid_t sys_clone3(struct clone_args *args)
31 return syscall(__NR_clone3, args, sizeof(struct clone_args));
34 static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
37 return syscall(__NR_waitid, which, pid, info, options, ru);
43 pid_t parent_tid = -1;
44 struct clone_args args = {
45 .parent_tid = ptr_to_u64(&parent_tid),
46 .pidfd = ptr_to_u64(&pidfd),
47 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
48 .exit_signal = SIGCHLD,
55 pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
58 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
60 EXPECT_EQ(close(pidfd), 0);
63 pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
66 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
68 EXPECT_EQ(close(pidfd), 0);
71 pid = sys_clone3(&args);
77 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
79 ASSERT_EQ(WIFEXITED(info.si_status), true);
80 ASSERT_EQ(WEXITSTATUS(info.si_status), 0);
81 EXPECT_EQ(close(pidfd), 0);
83 ASSERT_EQ(info.si_signo, SIGCHLD);
84 ASSERT_EQ(info.si_code, CLD_EXITED);
85 ASSERT_EQ(info.si_pid, parent_tid);
91 pid_t parent_tid = -1;
92 struct clone_args args = {
93 .parent_tid = ptr_to_u64(&parent_tid),
94 .pidfd = ptr_to_u64(&pidfd),
95 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
96 .exit_signal = SIGCHLD,
104 ASSERT_EQ(pipe(pfd), 0);
105 pid = sys_clone3(&args);
112 kill(getpid(), SIGSTOP);
113 ASSERT_EQ(read(pfd[0], buf, 1), 1);
115 kill(getpid(), SIGSTOP);
120 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
121 ASSERT_EQ(info.si_signo, SIGCHLD);
122 ASSERT_EQ(info.si_code, CLD_STOPPED);
123 ASSERT_EQ(info.si_pid, parent_tid);
125 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
127 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL), 0);
128 ASSERT_EQ(write(pfd[1], "C", 1), 1);
130 ASSERT_EQ(info.si_signo, SIGCHLD);
131 ASSERT_EQ(info.si_code, CLD_CONTINUED);
132 ASSERT_EQ(info.si_pid, parent_tid);
134 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL), 0);
135 ASSERT_EQ(info.si_signo, SIGCHLD);
136 ASSERT_EQ(info.si_code, CLD_STOPPED);
137 ASSERT_EQ(info.si_pid, parent_tid);
139 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0);
141 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
142 ASSERT_EQ(info.si_signo, SIGCHLD);
143 ASSERT_EQ(info.si_code, CLD_KILLED);
144 ASSERT_EQ(info.si_pid, parent_tid);
146 EXPECT_EQ(close(pidfd), 0);
152 unsigned int flags = 0;
153 pid_t parent_tid = -1;
154 struct clone_args args = {
155 .parent_tid = ptr_to_u64(&parent_tid),
156 .flags = CLONE_PARENT_SETTID,
157 .exit_signal = SIGCHLD,
166 * Callers need to see ECHILD with non-blocking pidfds when no child
169 pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK);
170 EXPECT_GE(pidfd, 0) {
171 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
172 ASSERT_EQ(errno, EINVAL);
173 SKIP(return, "Skipping PIDFD_NONBLOCK test");
176 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
178 ASSERT_EQ(errno, ECHILD);
179 EXPECT_EQ(close(pidfd), 0);
181 pid = sys_clone3(&args);
185 kill(getpid(), SIGSTOP);
189 pidfd = sys_pidfd_open(pid, PIDFD_NONBLOCK);
190 EXPECT_GE(pidfd, 0) {
191 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
192 ASSERT_EQ(errno, EINVAL);
193 SKIP(return, "Skipping PIDFD_NONBLOCK test");
196 flags = fcntl(pidfd, F_GETFL, 0);
198 ASSERT_GT((flags & O_NONBLOCK), 0);
201 * Callers need to see EAGAIN/EWOULDBLOCK with non-blocking pidfd when
202 * child processes exist but none have exited.
204 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
206 ASSERT_EQ(errno, EAGAIN);
209 * Callers need to continue seeing 0 with non-blocking pidfd and
210 * WNOHANG raised explicitly when child processes exist but none have
213 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG, NULL);
216 ASSERT_EQ(fcntl(pidfd, F_SETFL, (flags & ~O_NONBLOCK)), 0);
218 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
219 ASSERT_EQ(info.si_signo, SIGCHLD);
220 ASSERT_EQ(info.si_code, CLD_STOPPED);
221 ASSERT_EQ(info.si_pid, parent_tid);
223 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
225 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
226 ASSERT_EQ(info.si_signo, SIGCHLD);
227 ASSERT_EQ(info.si_code, CLD_EXITED);
228 ASSERT_EQ(info.si_pid, parent_tid);
230 EXPECT_EQ(close(pidfd), 0);