linux/tools/testing/selftests/pidfd/pidfd_poll_test.c
<<
>>
Prefs
   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
  20static bool timeout;
  21
  22static void handle_alarm(int sig)
  23{
  24        timeout = true;
  25}
  26
  27int 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