pidfd_poll_test.c 2.4 KB

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