1 // SPDX-License-Identifier: GPL-2.0 2 3 #define _GNU_SOURCE 4 #include <errno.h> 5 #include <linux/types.h> 6 #include <linux/wait.h> 7 #include <poll.h> 8 #include <signal.h> 9 #include <stdbool.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <syscall.h> 14 #include <sys/wait.h> 15 #include <unistd.h> 16 17 #include "pidfd.h" 18 #include "../kselftest.h" 19 20 static bool timeout; 21 22 static void handle_alarm(int sig) 23 { 24 timeout = true; 25 } 26 27 int main(int argc, char **argv) 28 { 29 struct pollfd fds; 30 int iter, nevents; 31 int nr_iterations = 10000; 32 33 fds.events = POLLIN; 34 35 if (argc > 2) 36 ksft_exit_fail_msg("Unexpected command line argument\n"); 37 38 if (argc == 2) { 39 nr_iterations = atoi(argv[1]); 40 if (nr_iterations <= 0) 41 ksft_exit_fail_msg("invalid input parameter %s\n", 42 argv[1]); 43 } 44 45 ksft_print_msg("running pidfd poll test for %d iterations\n", 46 nr_iterations); 47 48 for (iter = 0; iter < nr_iterations; iter++) { 49 int pidfd; 50 int child_pid = fork(); 51 52 if (child_pid < 0) { 53 if (errno == EAGAIN) { 54 iter--; 55 continue; 56 } 57 ksft_exit_fail_msg( 58 "%s - failed to fork a child process\n", 59 strerror(errno)); 60 } 61 62 if (child_pid == 0) { 63 /* Child process just sleeps for a min and exits */ 64 sleep(60); 65 exit(EXIT_SUCCESS); 66 } 67 68 /* Parent kills the child and waits for its death */ 69 pidfd = sys_pidfd_open(child_pid, 0); 70 if (pidfd < 0) 71 ksft_exit_fail_msg("%s - pidfd_open failed\n", 72 strerror(errno)); 73 74 /* Setup 3 sec alarm - plenty of time */ 75 if (signal(SIGALRM, handle_alarm) == SIG_ERR) 76 ksft_exit_fail_msg("%s - signal failed\n", 77 strerror(errno)); 78 alarm(3); 79 80 /* Send SIGKILL to the child */ 81 if (sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0)) 82 ksft_exit_fail_msg("%s - pidfd_send_signal failed\n", 83 strerror(errno)); 84 85 /* Wait for the death notification */ 86 fds.fd = pidfd; 87 nevents = poll(&fds, 1, -1); 88 89 /* Check for error conditions */ 90 if (nevents < 0) 91 ksft_exit_fail_msg("%s - poll failed\n", 92 strerror(errno)); 93 94 if (nevents != 1) 95 ksft_exit_fail_msg("unexpected poll result: %d\n", 96 nevents); 97 98 if (!(fds.revents & POLLIN)) 99 ksft_exit_fail_msg( 100 "unexpected event type received: 0x%x\n", 101 fds.revents); 102 103 if (timeout) 104 ksft_exit_fail_msg( 105 "death notification wait timeout\n"); 106 107 close(pidfd); 108 /* Wait for child to prevent zombies */ 109 if (waitpid(child_pid, NULL, 0) < 0) 110 ksft_exit_fail_msg("%s - waitpid failed\n", 111 strerror(errno)); 112 113 } 114 115 ksft_test_result_pass("pidfd poll test: pass\n"); 116 return ksft_exit_pass(); 117 } 118