pidfd_wait.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #define _GNU_SOURCE
  3. #include <errno.h>
  4. #include <linux/sched.h>
  5. #include <linux/types.h>
  6. #include <signal.h>
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <sched.h>
  11. #include <string.h>
  12. #include <sys/resource.h>
  13. #include <sys/time.h>
  14. #include <sys/types.h>
  15. #include <sys/wait.h>
  16. #include <unistd.h>
  17. #include "pidfd.h"
  18. #include "../kselftest_harness.h"
  19. #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
  20. /* Attempt to de-conflict with the selftests tree. */
  21. #ifndef SKIP
  22. #define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__)
  23. #endif
  24. static pid_t sys_clone3(struct clone_args *args)
  25. {
  26. return syscall(__NR_clone3, args, sizeof(struct clone_args));
  27. }
  28. static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
  29. struct rusage *ru)
  30. {
  31. return syscall(__NR_waitid, which, pid, info, options, ru);
  32. }
  33. TEST(wait_simple)
  34. {
  35. int pidfd = -1;
  36. pid_t parent_tid = -1;
  37. struct clone_args args = {
  38. .parent_tid = ptr_to_u64(&parent_tid),
  39. .pidfd = ptr_to_u64(&pidfd),
  40. .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
  41. .exit_signal = SIGCHLD,
  42. };
  43. pid_t pid;
  44. siginfo_t info = {
  45. .si_signo = 0,
  46. };
  47. pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
  48. ASSERT_GE(pidfd, 0);
  49. pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
  50. ASSERT_NE(pid, 0);
  51. EXPECT_EQ(close(pidfd), 0);
  52. pidfd = -1;
  53. pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
  54. ASSERT_GE(pidfd, 0);
  55. pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
  56. ASSERT_NE(pid, 0);
  57. EXPECT_EQ(close(pidfd), 0);
  58. pidfd = -1;
  59. pid = sys_clone3(&args);
  60. ASSERT_GE(pid, 0);
  61. if (pid == 0)
  62. exit(EXIT_SUCCESS);
  63. pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
  64. ASSERT_GE(pid, 0);
  65. ASSERT_EQ(WIFEXITED(info.si_status), true);
  66. ASSERT_EQ(WEXITSTATUS(info.si_status), 0);
  67. EXPECT_EQ(close(pidfd), 0);
  68. ASSERT_EQ(info.si_signo, SIGCHLD);
  69. ASSERT_EQ(info.si_code, CLD_EXITED);
  70. ASSERT_EQ(info.si_pid, parent_tid);
  71. }
  72. TEST(wait_states)
  73. {
  74. int pidfd = -1;
  75. pid_t parent_tid = -1;
  76. struct clone_args args = {
  77. .parent_tid = ptr_to_u64(&parent_tid),
  78. .pidfd = ptr_to_u64(&pidfd),
  79. .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
  80. .exit_signal = SIGCHLD,
  81. };
  82. int pfd[2];
  83. pid_t pid;
  84. siginfo_t info = {
  85. .si_signo = 0,
  86. };
  87. ASSERT_EQ(pipe(pfd), 0);
  88. pid = sys_clone3(&args);
  89. ASSERT_GE(pid, 0);
  90. if (pid == 0) {
  91. char buf[2];
  92. close(pfd[1]);
  93. kill(getpid(), SIGSTOP);
  94. ASSERT_EQ(read(pfd[0], buf, 1), 1);
  95. close(pfd[0]);
  96. kill(getpid(), SIGSTOP);
  97. exit(EXIT_SUCCESS);
  98. }
  99. close(pfd[0]);
  100. ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
  101. ASSERT_EQ(info.si_signo, SIGCHLD);
  102. ASSERT_EQ(info.si_code, CLD_STOPPED);
  103. ASSERT_EQ(info.si_pid, parent_tid);
  104. ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
  105. ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL), 0);
  106. ASSERT_EQ(write(pfd[1], "C", 1), 1);
  107. close(pfd[1]);
  108. ASSERT_EQ(info.si_signo, SIGCHLD);
  109. ASSERT_EQ(info.si_code, CLD_CONTINUED);
  110. ASSERT_EQ(info.si_pid, parent_tid);
  111. ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL), 0);
  112. ASSERT_EQ(info.si_signo, SIGCHLD);
  113. ASSERT_EQ(info.si_code, CLD_STOPPED);
  114. ASSERT_EQ(info.si_pid, parent_tid);
  115. ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0);
  116. ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
  117. ASSERT_EQ(info.si_signo, SIGCHLD);
  118. ASSERT_EQ(info.si_code, CLD_KILLED);
  119. ASSERT_EQ(info.si_pid, parent_tid);
  120. EXPECT_EQ(close(pidfd), 0);
  121. }
  122. TEST(wait_nonblock)
  123. {
  124. int pidfd;
  125. unsigned int flags = 0;
  126. pid_t parent_tid = -1;
  127. struct clone_args args = {
  128. .parent_tid = ptr_to_u64(&parent_tid),
  129. .flags = CLONE_PARENT_SETTID,
  130. .exit_signal = SIGCHLD,
  131. };
  132. int ret;
  133. pid_t pid;
  134. siginfo_t info = {
  135. .si_signo = 0,
  136. };
  137. /*
  138. * Callers need to see ECHILD with non-blocking pidfds when no child
  139. * processes exists.
  140. */
  141. pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK);
  142. EXPECT_GE(pidfd, 0) {
  143. /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
  144. ASSERT_EQ(errno, EINVAL);
  145. SKIP(return, "Skipping PIDFD_NONBLOCK test");
  146. }
  147. ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
  148. ASSERT_LT(ret, 0);
  149. ASSERT_EQ(errno, ECHILD);
  150. EXPECT_EQ(close(pidfd), 0);
  151. pid = sys_clone3(&args);
  152. ASSERT_GE(pid, 0);
  153. if (pid == 0) {
  154. kill(getpid(), SIGSTOP);
  155. exit(EXIT_SUCCESS);
  156. }
  157. pidfd = sys_pidfd_open(pid, PIDFD_NONBLOCK);
  158. EXPECT_GE(pidfd, 0) {
  159. /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
  160. ASSERT_EQ(errno, EINVAL);
  161. SKIP(return, "Skipping PIDFD_NONBLOCK test");
  162. }
  163. flags = fcntl(pidfd, F_GETFL, 0);
  164. ASSERT_GT(flags, 0);
  165. ASSERT_GT((flags & O_NONBLOCK), 0);
  166. /*
  167. * Callers need to see EAGAIN/EWOULDBLOCK with non-blocking pidfd when
  168. * child processes exist but none have exited.
  169. */
  170. ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
  171. ASSERT_LT(ret, 0);
  172. ASSERT_EQ(errno, EAGAIN);
  173. /*
  174. * Callers need to continue seeing 0 with non-blocking pidfd and
  175. * WNOHANG raised explicitly when child processes exist but none have
  176. * exited.
  177. */
  178. ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG, NULL);
  179. ASSERT_EQ(ret, 0);
  180. ASSERT_EQ(fcntl(pidfd, F_SETFL, (flags & ~O_NONBLOCK)), 0);
  181. ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
  182. ASSERT_EQ(info.si_signo, SIGCHLD);
  183. ASSERT_EQ(info.si_code, CLD_STOPPED);
  184. ASSERT_EQ(info.si_pid, parent_tid);
  185. ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
  186. ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
  187. ASSERT_EQ(info.si_signo, SIGCHLD);
  188. ASSERT_EQ(info.si_code, CLD_EXITED);
  189. ASSERT_EQ(info.si_pid, parent_tid);
  190. EXPECT_EQ(close(pidfd), 0);
  191. }
  192. TEST_HARNESS_MAIN