Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
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 /* Attempt to de-conflict with the selftests tree. */
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      * Callers need to see ECHILD with non-blocking pidfds when no child
0157      * processes exists.
0158      */
0159     pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK);
0160     EXPECT_GE(pidfd, 0) {
0161         /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
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         /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
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      * Callers need to see EAGAIN/EWOULDBLOCK with non-blocking pidfd when
0192      * child processes exist but none have exited.
0193      */
0194     ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
0195     ASSERT_LT(ret, 0);
0196     ASSERT_EQ(errno, EAGAIN);
0197 
0198     /*
0199      * Callers need to continue seeing 0 with non-blocking pidfd and
0200      * WNOHANG raised explicitly when child processes exist but none have
0201      * exited.
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