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/types.h>
0006 #include <poll.h>
0007 #include <signal.h>
0008 #include <stdbool.h>
0009 #include <stdio.h>
0010 #include <stdlib.h>
0011 #include <string.h>
0012 #include <syscall.h>
0013 #include <sys/wait.h>
0014 #include <unistd.h>
0015 
0016 #include "pidfd.h"
0017 #include "../kselftest.h"
0018 
0019 static bool timeout;
0020 
0021 static void handle_alarm(int sig)
0022 {
0023     timeout = true;
0024 }
0025 
0026 int main(int argc, char **argv)
0027 {
0028     struct pollfd fds;
0029     int iter, nevents;
0030     int nr_iterations = 10000;
0031 
0032     fds.events = POLLIN;
0033 
0034     if (argc > 2)
0035         ksft_exit_fail_msg("Unexpected command line argument\n");
0036 
0037     if (argc == 2) {
0038         nr_iterations = atoi(argv[1]);
0039         if (nr_iterations <= 0)
0040             ksft_exit_fail_msg("invalid input parameter %s\n",
0041                     argv[1]);
0042     }
0043 
0044     ksft_print_msg("running pidfd poll test for %d iterations\n",
0045         nr_iterations);
0046 
0047     for (iter = 0; iter < nr_iterations; iter++) {
0048         int pidfd;
0049         int child_pid = fork();
0050 
0051         if (child_pid < 0) {
0052             if (errno == EAGAIN) {
0053                 iter--;
0054                 continue;
0055             }
0056             ksft_exit_fail_msg(
0057                 "%s - failed to fork a child process\n",
0058                 strerror(errno));
0059         }
0060 
0061         if (child_pid == 0) {
0062             /* Child process just sleeps for a min and exits */
0063             sleep(60);
0064             exit(EXIT_SUCCESS);
0065         }
0066 
0067         /* Parent kills the child and waits for its death */
0068         pidfd = sys_pidfd_open(child_pid, 0);
0069         if (pidfd < 0)
0070             ksft_exit_fail_msg("%s - pidfd_open failed\n",
0071                     strerror(errno));
0072 
0073         /* Setup 3 sec alarm - plenty of time */
0074         if (signal(SIGALRM, handle_alarm) == SIG_ERR)
0075             ksft_exit_fail_msg("%s - signal failed\n",
0076                     strerror(errno));
0077         alarm(3);
0078 
0079         /* Send SIGKILL to the child */
0080         if (sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0))
0081             ksft_exit_fail_msg("%s - pidfd_send_signal failed\n",
0082                     strerror(errno));
0083 
0084         /* Wait for the death notification */
0085         fds.fd = pidfd;
0086         nevents = poll(&fds, 1, -1);
0087 
0088         /* Check for error conditions */
0089         if (nevents < 0)
0090             ksft_exit_fail_msg("%s - poll failed\n",
0091                     strerror(errno));
0092 
0093         if (nevents != 1)
0094             ksft_exit_fail_msg("unexpected poll result: %d\n",
0095                     nevents);
0096 
0097         if (!(fds.revents & POLLIN))
0098             ksft_exit_fail_msg(
0099                 "unexpected event type received: 0x%x\n",
0100                 fds.revents);
0101 
0102         if (timeout)
0103             ksft_exit_fail_msg(
0104                 "death notification wait timeout\n");
0105 
0106         close(pidfd);
0107         /* Wait for child to prevent zombies */
0108         if (waitpid(child_pid, NULL, 0) < 0)
0109             ksft_exit_fail_msg("%s - waitpid failed\n",
0110                     strerror(errno));
0111 
0112     }
0113 
0114     ksft_test_result_pass("pidfd poll test: pass\n");
0115     return ksft_exit_pass();
0116 }