root/tools/testing/selftests/pidfd/pidfd_wait.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_clone3
  2. sys_waitid
  3. test_pidfd_wait_simple
  4. test_pidfd_wait_states
  5. main

   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.h"
  21 
  22 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
  23 
  24 static pid_t sys_clone3(struct clone_args *args)
  25 {
  26         return syscall(__NR_clone3, args, sizeof(struct clone_args));
  27 }
  28 
  29 static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
  30                       struct rusage *ru)
  31 {
  32         return syscall(__NR_waitid, which, pid, info, options, ru);
  33 }
  34 
  35 static int test_pidfd_wait_simple(void)
  36 {
  37         const char *test_name = "pidfd wait simple";
  38         int pidfd = -1, status = 0;
  39         pid_t parent_tid = -1;
  40         struct clone_args args = {
  41                 .parent_tid = ptr_to_u64(&parent_tid),
  42                 .pidfd = ptr_to_u64(&pidfd),
  43                 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
  44                 .exit_signal = SIGCHLD,
  45         };
  46         int ret;
  47         pid_t pid;
  48         siginfo_t info = {
  49                 .si_signo = 0,
  50         };
  51 
  52         pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
  53         if (pidfd < 0)
  54                 ksft_exit_fail_msg("%s test: failed to open /proc/self %s\n",
  55                                    test_name, strerror(errno));
  56 
  57         pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
  58         if (pid == 0)
  59                 ksft_exit_fail_msg(
  60                         "%s test: succeeded to wait on invalid pidfd %s\n",
  61                         test_name, strerror(errno));
  62         close(pidfd);
  63         pidfd = -1;
  64 
  65         pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
  66         if (pidfd == 0)
  67                 ksft_exit_fail_msg("%s test: failed to open /dev/null %s\n",
  68                                    test_name, strerror(errno));
  69 
  70         pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
  71         if (pid == 0)
  72                 ksft_exit_fail_msg(
  73                         "%s test: succeeded to wait on invalid pidfd %s\n",
  74                         test_name, strerror(errno));
  75         close(pidfd);
  76         pidfd = -1;
  77 
  78         pid = sys_clone3(&args);
  79         if (pid < 0)
  80                 ksft_exit_fail_msg("%s test: failed to create new process %s\n",
  81                                    test_name, strerror(errno));
  82 
  83         if (pid == 0)
  84                 exit(EXIT_SUCCESS);
  85 
  86         pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
  87         if (pid < 0)
  88                 ksft_exit_fail_msg(
  89                         "%s test: failed to wait on process with pid %d and pidfd %d: %s\n",
  90                         test_name, parent_tid, pidfd, strerror(errno));
  91 
  92         if (!WIFEXITED(info.si_status) || WEXITSTATUS(info.si_status))
  93                 ksft_exit_fail_msg(
  94                         "%s test: unexpected status received after waiting on process with pid %d and pidfd %d: %s\n",
  95                         test_name, parent_tid, pidfd, strerror(errno));
  96         close(pidfd);
  97 
  98         if (info.si_signo != SIGCHLD)
  99                 ksft_exit_fail_msg(
 100                         "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 101                         test_name, info.si_signo, parent_tid, pidfd,
 102                         strerror(errno));
 103 
 104         if (info.si_code != CLD_EXITED)
 105                 ksft_exit_fail_msg(
 106                         "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 107                         test_name, info.si_code, parent_tid, pidfd,
 108                         strerror(errno));
 109 
 110         if (info.si_pid != parent_tid)
 111                 ksft_exit_fail_msg(
 112                         "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 113                         test_name, info.si_pid, parent_tid, pidfd,
 114                         strerror(errno));
 115 
 116         ksft_test_result_pass("%s test: Passed\n", test_name);
 117         return 0;
 118 }
 119 
 120 static int test_pidfd_wait_states(void)
 121 {
 122         const char *test_name = "pidfd wait states";
 123         int pidfd = -1, status = 0;
 124         pid_t parent_tid = -1;
 125         struct clone_args args = {
 126                 .parent_tid = ptr_to_u64(&parent_tid),
 127                 .pidfd = ptr_to_u64(&pidfd),
 128                 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
 129                 .exit_signal = SIGCHLD,
 130         };
 131         int ret;
 132         pid_t pid;
 133         siginfo_t info = {
 134                 .si_signo = 0,
 135         };
 136 
 137         pid = sys_clone3(&args);
 138         if (pid < 0)
 139                 ksft_exit_fail_msg("%s test: failed to create new process %s\n",
 140                                    test_name, strerror(errno));
 141 
 142         if (pid == 0) {
 143                 kill(getpid(), SIGSTOP);
 144                 kill(getpid(), SIGSTOP);
 145                 exit(EXIT_SUCCESS);
 146         }
 147 
 148         ret = sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL);
 149         if (ret < 0)
 150                 ksft_exit_fail_msg(
 151                         "%s test: failed to wait on WSTOPPED process with pid %d and pidfd %d: %s\n",
 152                         test_name, parent_tid, pidfd, strerror(errno));
 153 
 154         if (info.si_signo != SIGCHLD)
 155                 ksft_exit_fail_msg(
 156                         "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 157                         test_name, info.si_signo, parent_tid, pidfd,
 158                         strerror(errno));
 159 
 160         if (info.si_code != CLD_STOPPED)
 161                 ksft_exit_fail_msg(
 162                         "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 163                         test_name, info.si_code, parent_tid, pidfd,
 164                         strerror(errno));
 165 
 166         if (info.si_pid != parent_tid)
 167                 ksft_exit_fail_msg(
 168                         "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 169                         test_name, info.si_pid, parent_tid, pidfd,
 170                         strerror(errno));
 171 
 172         ret = sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0);
 173         if (ret < 0)
 174                 ksft_exit_fail_msg(
 175                         "%s test: failed to send signal to process with pid %d and pidfd %d: %s\n",
 176                         test_name, parent_tid, pidfd, strerror(errno));
 177 
 178         ret = sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL);
 179         if (ret < 0)
 180                 ksft_exit_fail_msg(
 181                         "%s test: failed to wait WCONTINUED on process with pid %d and pidfd %d: %s\n",
 182                         test_name, parent_tid, pidfd, strerror(errno));
 183 
 184         if (info.si_signo != SIGCHLD)
 185                 ksft_exit_fail_msg(
 186                         "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 187                         test_name, info.si_signo, parent_tid, pidfd,
 188                         strerror(errno));
 189 
 190         if (info.si_code != CLD_CONTINUED)
 191                 ksft_exit_fail_msg(
 192                         "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 193                         test_name, info.si_code, parent_tid, pidfd,
 194                         strerror(errno));
 195 
 196         if (info.si_pid != parent_tid)
 197                 ksft_exit_fail_msg(
 198                         "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 199                         test_name, info.si_pid, parent_tid, pidfd,
 200                         strerror(errno));
 201 
 202         ret = sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL);
 203         if (ret < 0)
 204                 ksft_exit_fail_msg(
 205                         "%s test: failed to wait on WUNTRACED process with pid %d and pidfd %d: %s\n",
 206                         test_name, parent_tid, pidfd, strerror(errno));
 207 
 208         if (info.si_signo != SIGCHLD)
 209                 ksft_exit_fail_msg(
 210                         "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 211                         test_name, info.si_signo, parent_tid, pidfd,
 212                         strerror(errno));
 213 
 214         if (info.si_code != CLD_STOPPED)
 215                 ksft_exit_fail_msg(
 216                         "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 217                         test_name, info.si_code, parent_tid, pidfd,
 218                         strerror(errno));
 219 
 220         if (info.si_pid != parent_tid)
 221                 ksft_exit_fail_msg(
 222                         "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 223                         test_name, info.si_pid, parent_tid, pidfd,
 224                         strerror(errno));
 225 
 226         ret = sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
 227         if (ret < 0)
 228                 ksft_exit_fail_msg(
 229                         "%s test: failed to send SIGKILL to process with pid %d and pidfd %d: %s\n",
 230                         test_name, parent_tid, pidfd, strerror(errno));
 231 
 232         ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
 233         if (ret < 0)
 234                 ksft_exit_fail_msg(
 235                         "%s test: failed to wait on WEXITED process with pid %d and pidfd %d: %s\n",
 236                         test_name, parent_tid, pidfd, strerror(errno));
 237 
 238         if (info.si_signo != SIGCHLD)
 239                 ksft_exit_fail_msg(
 240                         "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 241                         test_name, info.si_signo, parent_tid, pidfd,
 242                         strerror(errno));
 243 
 244         if (info.si_code != CLD_KILLED)
 245                 ksft_exit_fail_msg(
 246                         "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 247                         test_name, info.si_code, parent_tid, pidfd,
 248                         strerror(errno));
 249 
 250         if (info.si_pid != parent_tid)
 251                 ksft_exit_fail_msg(
 252                         "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
 253                         test_name, info.si_pid, parent_tid, pidfd,
 254                         strerror(errno));
 255 
 256         close(pidfd);
 257 
 258         ksft_test_result_pass("%s test: Passed\n", test_name);
 259         return 0;
 260 }
 261 
 262 int main(int argc, char **argv)
 263 {
 264         ksft_print_header();
 265         ksft_set_plan(2);
 266 
 267         test_pidfd_wait_simple();
 268         test_pidfd_wait_states();
 269 
 270         return ksft_exit_pass();
 271 }

/* [<][>][^][v][top][bottom][index][help] */