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