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);