drm/panel: panel-himax-hx83102: support for csot-pna957qt1-1 MIPI-DSI panel
[drm/drm-misc.git] / tools / testing / selftests / pidfd / pidfd_wait.c
blob1e2d49751cdee6a62a24aae31d1465eb8d8421ad
1 /* SPDX-License-Identifier: GPL-2.0 */
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <linux/sched.h>
6 #include <linux/types.h>
7 #include <signal.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sched.h>
12 #include <string.h>
13 #include <sys/resource.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17 #include <unistd.h>
19 #include "pidfd.h"
20 #include "../kselftest_harness.h"
22 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
24 /* Attempt to de-conflict with the selftests tree. */
25 #ifndef SKIP
26 #define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__)
27 #endif
29 TEST(wait_simple)
31 int pidfd = -1;
32 pid_t parent_tid = -1;
33 struct __clone_args args = {
34 .parent_tid = ptr_to_u64(&parent_tid),
35 .pidfd = ptr_to_u64(&pidfd),
36 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
37 .exit_signal = SIGCHLD,
39 pid_t pid;
40 siginfo_t info = {
41 .si_signo = 0,
44 pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
45 ASSERT_GE(pidfd, 0);
47 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
48 ASSERT_NE(pid, 0);
49 EXPECT_EQ(close(pidfd), 0);
50 pidfd = -1;
52 pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
53 ASSERT_GE(pidfd, 0);
55 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
56 ASSERT_NE(pid, 0);
57 EXPECT_EQ(close(pidfd), 0);
58 pidfd = -1;
60 pid = sys_clone3(&args, sizeof(args));
61 ASSERT_GE(pid, 0);
63 if (pid == 0)
64 exit(EXIT_SUCCESS);
66 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
67 ASSERT_GE(pid, 0);
68 ASSERT_EQ(WIFEXITED(info.si_status), true);
69 ASSERT_EQ(WEXITSTATUS(info.si_status), 0);
70 EXPECT_EQ(close(pidfd), 0);
72 ASSERT_EQ(info.si_signo, SIGCHLD);
73 ASSERT_EQ(info.si_code, CLD_EXITED);
74 ASSERT_EQ(info.si_pid, parent_tid);
77 TEST(wait_states)
79 int pidfd = -1;
80 pid_t parent_tid = -1;
81 struct __clone_args args = {
82 .parent_tid = ptr_to_u64(&parent_tid),
83 .pidfd = ptr_to_u64(&pidfd),
84 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
85 .exit_signal = SIGCHLD,
87 int pfd[2];
88 pid_t pid;
89 siginfo_t info = {
90 .si_signo = 0,
93 ASSERT_EQ(pipe(pfd), 0);
94 pid = sys_clone3(&args, sizeof(args));
95 ASSERT_GE(pid, 0);
97 if (pid == 0) {
98 char buf[2];
100 close(pfd[1]);
101 kill(getpid(), SIGSTOP);
102 ASSERT_EQ(read(pfd[0], buf, 1), 1);
103 close(pfd[0]);
104 kill(getpid(), SIGSTOP);
105 exit(EXIT_SUCCESS);
108 close(pfd[0]);
109 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED), 0);
110 ASSERT_EQ(info.si_signo, SIGCHLD);
111 ASSERT_EQ(info.si_code, CLD_STOPPED);
112 ASSERT_EQ(info.si_pid, parent_tid);
114 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
116 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED), 0);
117 ASSERT_EQ(write(pfd[1], "C", 1), 1);
118 close(pfd[1]);
119 ASSERT_EQ(info.si_signo, SIGCHLD);
120 ASSERT_EQ(info.si_code, CLD_CONTINUED);
121 ASSERT_EQ(info.si_pid, parent_tid);
123 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED), 0);
124 ASSERT_EQ(info.si_signo, SIGCHLD);
125 ASSERT_EQ(info.si_code, CLD_STOPPED);
126 ASSERT_EQ(info.si_pid, parent_tid);
128 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0);
130 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED), 0);
131 ASSERT_EQ(info.si_signo, SIGCHLD);
132 ASSERT_EQ(info.si_code, CLD_KILLED);
133 ASSERT_EQ(info.si_pid, parent_tid);
135 EXPECT_EQ(close(pidfd), 0);
138 TEST(wait_nonblock)
140 int pidfd;
141 unsigned int flags = 0;
142 pid_t parent_tid = -1;
143 struct __clone_args args = {
144 .parent_tid = ptr_to_u64(&parent_tid),
145 .flags = CLONE_PARENT_SETTID,
146 .exit_signal = SIGCHLD,
148 int ret;
149 pid_t pid;
150 siginfo_t info = {
151 .si_signo = 0,
155 * Callers need to see ECHILD with non-blocking pidfds when no child
156 * processes exists.
158 pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK);
159 EXPECT_GE(pidfd, 0) {
160 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
161 ASSERT_EQ(errno, EINVAL);
162 SKIP(return, "Skipping PIDFD_NONBLOCK test");
165 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
166 ASSERT_LT(ret, 0);
167 ASSERT_EQ(errno, ECHILD);
168 EXPECT_EQ(close(pidfd), 0);
170 pid = sys_clone3(&args, sizeof(args));
171 ASSERT_GE(pid, 0);
173 if (pid == 0) {
174 kill(getpid(), SIGSTOP);
175 exit(EXIT_SUCCESS);
178 pidfd = sys_pidfd_open(pid, PIDFD_NONBLOCK);
179 EXPECT_GE(pidfd, 0) {
180 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
181 ASSERT_EQ(errno, EINVAL);
182 SKIP(return, "Skipping PIDFD_NONBLOCK test");
185 flags = fcntl(pidfd, F_GETFL, 0);
186 ASSERT_GT(flags, 0);
187 ASSERT_GT((flags & O_NONBLOCK), 0);
190 * Callers need to see EAGAIN/EWOULDBLOCK with non-blocking pidfd when
191 * child processes exist but none have exited.
193 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED);
194 ASSERT_LT(ret, 0);
195 ASSERT_EQ(errno, EAGAIN);
198 * Callers need to continue seeing 0 with non-blocking pidfd and
199 * WNOHANG raised explicitly when child processes exist but none have
200 * exited.
202 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG);
203 ASSERT_EQ(ret, 0);
205 ASSERT_EQ(fcntl(pidfd, F_SETFL, (flags & ~O_NONBLOCK)), 0);
207 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED), 0);
208 ASSERT_EQ(info.si_signo, SIGCHLD);
209 ASSERT_EQ(info.si_code, CLD_STOPPED);
210 ASSERT_EQ(info.si_pid, parent_tid);
212 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
214 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED), 0);
215 ASSERT_EQ(info.si_signo, SIGCHLD);
216 ASSERT_EQ(info.si_code, CLD_EXITED);
217 ASSERT_EQ(info.si_pid, parent_tid);
219 EXPECT_EQ(close(pidfd), 0);
222 TEST_HARNESS_MAIN