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