0001
0002
0003 #define _GNU_SOURCE
0004 #include <errno.h>
0005 #include <linux/sched.h>
0006 #include <linux/types.h>
0007 #include <signal.h>
0008 #include <stdint.h>
0009 #include <stdio.h>
0010 #include <stdlib.h>
0011 #include <sched.h>
0012 #include <string.h>
0013 #include <sys/resource.h>
0014 #include <sys/time.h>
0015 #include <sys/types.h>
0016 #include <sys/wait.h>
0017 #include <unistd.h>
0018
0019 #include "pidfd.h"
0020 #include "../kselftest_harness.h"
0021
0022 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
0023
0024
0025 #ifndef SKIP
0026 #define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__)
0027 #endif
0028
0029 static pid_t sys_clone3(struct clone_args *args)
0030 {
0031 return syscall(__NR_clone3, args, sizeof(struct clone_args));
0032 }
0033
0034 static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
0035 struct rusage *ru)
0036 {
0037 return syscall(__NR_waitid, which, pid, info, options, ru);
0038 }
0039
0040 TEST(wait_simple)
0041 {
0042 int pidfd = -1;
0043 pid_t parent_tid = -1;
0044 struct clone_args args = {
0045 .parent_tid = ptr_to_u64(&parent_tid),
0046 .pidfd = ptr_to_u64(&pidfd),
0047 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
0048 .exit_signal = SIGCHLD,
0049 };
0050 pid_t pid;
0051 siginfo_t info = {
0052 .si_signo = 0,
0053 };
0054
0055 pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
0056 ASSERT_GE(pidfd, 0);
0057
0058 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
0059 ASSERT_NE(pid, 0);
0060 EXPECT_EQ(close(pidfd), 0);
0061 pidfd = -1;
0062
0063 pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
0064 ASSERT_GE(pidfd, 0);
0065
0066 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
0067 ASSERT_NE(pid, 0);
0068 EXPECT_EQ(close(pidfd), 0);
0069 pidfd = -1;
0070
0071 pid = sys_clone3(&args);
0072 ASSERT_GE(pid, 0);
0073
0074 if (pid == 0)
0075 exit(EXIT_SUCCESS);
0076
0077 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
0078 ASSERT_GE(pid, 0);
0079 ASSERT_EQ(WIFEXITED(info.si_status), true);
0080 ASSERT_EQ(WEXITSTATUS(info.si_status), 0);
0081 EXPECT_EQ(close(pidfd), 0);
0082
0083 ASSERT_EQ(info.si_signo, SIGCHLD);
0084 ASSERT_EQ(info.si_code, CLD_EXITED);
0085 ASSERT_EQ(info.si_pid, parent_tid);
0086 }
0087
0088 TEST(wait_states)
0089 {
0090 int pidfd = -1;
0091 pid_t parent_tid = -1;
0092 struct clone_args args = {
0093 .parent_tid = ptr_to_u64(&parent_tid),
0094 .pidfd = ptr_to_u64(&pidfd),
0095 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
0096 .exit_signal = SIGCHLD,
0097 };
0098 pid_t pid;
0099 siginfo_t info = {
0100 .si_signo = 0,
0101 };
0102
0103 pid = sys_clone3(&args);
0104 ASSERT_GE(pid, 0);
0105
0106 if (pid == 0) {
0107 kill(getpid(), SIGSTOP);
0108 kill(getpid(), SIGSTOP);
0109 exit(EXIT_SUCCESS);
0110 }
0111
0112 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
0113 ASSERT_EQ(info.si_signo, SIGCHLD);
0114 ASSERT_EQ(info.si_code, CLD_STOPPED);
0115 ASSERT_EQ(info.si_pid, parent_tid);
0116
0117 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
0118
0119 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL), 0);
0120 ASSERT_EQ(info.si_signo, SIGCHLD);
0121 ASSERT_EQ(info.si_code, CLD_CONTINUED);
0122 ASSERT_EQ(info.si_pid, parent_tid);
0123
0124 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL), 0);
0125 ASSERT_EQ(info.si_signo, SIGCHLD);
0126 ASSERT_EQ(info.si_code, CLD_STOPPED);
0127 ASSERT_EQ(info.si_pid, parent_tid);
0128
0129 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0);
0130
0131 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
0132 ASSERT_EQ(info.si_signo, SIGCHLD);
0133 ASSERT_EQ(info.si_code, CLD_KILLED);
0134 ASSERT_EQ(info.si_pid, parent_tid);
0135
0136 EXPECT_EQ(close(pidfd), 0);
0137 }
0138
0139 TEST(wait_nonblock)
0140 {
0141 int pidfd, status = 0;
0142 unsigned int flags = 0;
0143 pid_t parent_tid = -1;
0144 struct clone_args args = {
0145 .parent_tid = ptr_to_u64(&parent_tid),
0146 .flags = CLONE_PARENT_SETTID,
0147 .exit_signal = SIGCHLD,
0148 };
0149 int ret;
0150 pid_t pid;
0151 siginfo_t info = {
0152 .si_signo = 0,
0153 };
0154
0155
0156
0157
0158
0159 pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK);
0160 EXPECT_GE(pidfd, 0) {
0161
0162 ASSERT_EQ(errno, EINVAL);
0163 SKIP(return, "Skipping PIDFD_NONBLOCK test");
0164 }
0165
0166 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
0167 ASSERT_LT(ret, 0);
0168 ASSERT_EQ(errno, ECHILD);
0169 EXPECT_EQ(close(pidfd), 0);
0170
0171 pid = sys_clone3(&args);
0172 ASSERT_GE(pid, 0);
0173
0174 if (pid == 0) {
0175 kill(getpid(), SIGSTOP);
0176 exit(EXIT_SUCCESS);
0177 }
0178
0179 pidfd = sys_pidfd_open(pid, PIDFD_NONBLOCK);
0180 EXPECT_GE(pidfd, 0) {
0181
0182 ASSERT_EQ(errno, EINVAL);
0183 SKIP(return, "Skipping PIDFD_NONBLOCK test");
0184 }
0185
0186 flags = fcntl(pidfd, F_GETFL, 0);
0187 ASSERT_GT(flags, 0);
0188 ASSERT_GT((flags & O_NONBLOCK), 0);
0189
0190
0191
0192
0193
0194 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
0195 ASSERT_LT(ret, 0);
0196 ASSERT_EQ(errno, EAGAIN);
0197
0198
0199
0200
0201
0202
0203 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG, NULL);
0204 ASSERT_EQ(ret, 0);
0205
0206 ASSERT_EQ(fcntl(pidfd, F_SETFL, (flags & ~O_NONBLOCK)), 0);
0207
0208 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
0209 ASSERT_EQ(info.si_signo, SIGCHLD);
0210 ASSERT_EQ(info.si_code, CLD_STOPPED);
0211 ASSERT_EQ(info.si_pid, parent_tid);
0212
0213 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
0214
0215 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
0216 ASSERT_EQ(info.si_signo, SIGCHLD);
0217 ASSERT_EQ(info.si_code, CLD_EXITED);
0218 ASSERT_EQ(info.si_pid, parent_tid);
0219
0220 EXPECT_EQ(close(pidfd), 0);
0221 }
0222
0223 TEST_HARNESS_MAIN