Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1/* SPDX-License-Identifier: GPL-2.0 */
  2
  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>
 18
 19#include "pidfd.h"
 20#include "../kselftest.h"
 21
 22#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
 23
 24static pid_t sys_clone3(struct clone_args *args)
 25{
 26	return syscall(__NR_clone3, args, sizeof(struct clone_args));
 27}
 28
 29static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
 30		      struct rusage *ru)
 31{
 32	return syscall(__NR_waitid, which, pid, info, options, ru);
 33}
 34
 35static int test_pidfd_wait_simple(void)
 36{
 37	const char *test_name = "pidfd wait simple";
 38	int pidfd = -1, status = 0;
 39	pid_t parent_tid = -1;
 40	struct clone_args args = {
 41		.parent_tid = ptr_to_u64(&parent_tid),
 42		.pidfd = ptr_to_u64(&pidfd),
 43		.flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
 44		.exit_signal = SIGCHLD,
 45	};
 46	int ret;
 47	pid_t pid;
 48	siginfo_t info = {
 49		.si_signo = 0,
 50	};
 51
 52	pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
 53	if (pidfd < 0)
 54		ksft_exit_fail_msg("%s test: failed to open /proc/self %s\n",
 55				   test_name, strerror(errno));
 56
 57	pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
 58	if (pid == 0)
 59		ksft_exit_fail_msg(
 60			"%s test: succeeded to wait on invalid pidfd %s\n",
 61			test_name, strerror(errno));
 62	close(pidfd);
 63	pidfd = -1;
 64
 65	pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
 66	if (pidfd == 0)
 67		ksft_exit_fail_msg("%s test: failed to open /dev/null %s\n",
 68				   test_name, strerror(errno));
 69
 70	pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
 71	if (pid == 0)
 72		ksft_exit_fail_msg(
 73			"%s test: succeeded to wait on invalid pidfd %s\n",
 74			test_name, strerror(errno));
 75	close(pidfd);
 76	pidfd = -1;
 77
 78	pid = sys_clone3(&args);
 79	if (pid < 0)
 80		ksft_exit_fail_msg("%s test: failed to create new process %s\n",
 81				   test_name, strerror(errno));
 82
 83	if (pid == 0)
 84		exit(EXIT_SUCCESS);
 85
 86	pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
 87	if (pid < 0)
 88		ksft_exit_fail_msg(
 89			"%s test: failed to wait on process with pid %d and pidfd %d: %s\n",
 90			test_name, parent_tid, pidfd, strerror(errno));
 91
 92	if (!WIFEXITED(info.si_status) || WEXITSTATUS(info.si_status))
 93		ksft_exit_fail_msg(
 94			"%s test: unexpected status received after waiting on process with pid %d and pidfd %d: %s\n",
 95			test_name, parent_tid, pidfd, strerror(errno));
 96	close(pidfd);
 97
 98	if (info.si_signo != SIGCHLD)
 99		ksft_exit_fail_msg(
100			"%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
101			test_name, info.si_signo, parent_tid, pidfd,
102			strerror(errno));
103
104	if (info.si_code != CLD_EXITED)
105		ksft_exit_fail_msg(
106			"%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
107			test_name, info.si_code, parent_tid, pidfd,
108			strerror(errno));
109
110	if (info.si_pid != parent_tid)
111		ksft_exit_fail_msg(
112			"%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
113			test_name, info.si_pid, parent_tid, pidfd,
114			strerror(errno));
115
116	ksft_test_result_pass("%s test: Passed\n", test_name);
117	return 0;
118}
119
120static int test_pidfd_wait_states(void)
121{
122	const char *test_name = "pidfd wait states";
123	int pidfd = -1, status = 0;
124	pid_t parent_tid = -1;
125	struct clone_args args = {
126		.parent_tid = ptr_to_u64(&parent_tid),
127		.pidfd = ptr_to_u64(&pidfd),
128		.flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
129		.exit_signal = SIGCHLD,
130	};
131	int ret;
132	pid_t pid;
133	siginfo_t info = {
134		.si_signo = 0,
135	};
136
137	pid = sys_clone3(&args);
138	if (pid < 0)
139		ksft_exit_fail_msg("%s test: failed to create new process %s\n",
140				   test_name, strerror(errno));
141
142	if (pid == 0) {
143		kill(getpid(), SIGSTOP);
144		kill(getpid(), SIGSTOP);
145		exit(EXIT_SUCCESS);
146	}
147
148	ret = sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL);
149	if (ret < 0)
150		ksft_exit_fail_msg(
151			"%s test: failed to wait on WSTOPPED process with pid %d and pidfd %d: %s\n",
152			test_name, parent_tid, pidfd, strerror(errno));
153
154	if (info.si_signo != SIGCHLD)
155		ksft_exit_fail_msg(
156			"%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
157			test_name, info.si_signo, parent_tid, pidfd,
158			strerror(errno));
159
160	if (info.si_code != CLD_STOPPED)
161		ksft_exit_fail_msg(
162			"%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
163			test_name, info.si_code, parent_tid, pidfd,
164			strerror(errno));
165
166	if (info.si_pid != parent_tid)
167		ksft_exit_fail_msg(
168			"%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
169			test_name, info.si_pid, parent_tid, pidfd,
170			strerror(errno));
171
172	ret = sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0);
173	if (ret < 0)
174		ksft_exit_fail_msg(
175			"%s test: failed to send signal to process with pid %d and pidfd %d: %s\n",
176			test_name, parent_tid, pidfd, strerror(errno));
177
178	ret = sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL);
179	if (ret < 0)
180		ksft_exit_fail_msg(
181			"%s test: failed to wait WCONTINUED on process with pid %d and pidfd %d: %s\n",
182			test_name, parent_tid, pidfd, strerror(errno));
183
184	if (info.si_signo != SIGCHLD)
185		ksft_exit_fail_msg(
186			"%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
187			test_name, info.si_signo, parent_tid, pidfd,
188			strerror(errno));
189
190	if (info.si_code != CLD_CONTINUED)
191		ksft_exit_fail_msg(
192			"%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
193			test_name, info.si_code, parent_tid, pidfd,
194			strerror(errno));
195
196	if (info.si_pid != parent_tid)
197		ksft_exit_fail_msg(
198			"%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
199			test_name, info.si_pid, parent_tid, pidfd,
200			strerror(errno));
201
202	ret = sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL);
203	if (ret < 0)
204		ksft_exit_fail_msg(
205			"%s test: failed to wait on WUNTRACED process with pid %d and pidfd %d: %s\n",
206			test_name, parent_tid, pidfd, strerror(errno));
207
208	if (info.si_signo != SIGCHLD)
209		ksft_exit_fail_msg(
210			"%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
211			test_name, info.si_signo, parent_tid, pidfd,
212			strerror(errno));
213
214	if (info.si_code != CLD_STOPPED)
215		ksft_exit_fail_msg(
216			"%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
217			test_name, info.si_code, parent_tid, pidfd,
218			strerror(errno));
219
220	if (info.si_pid != parent_tid)
221		ksft_exit_fail_msg(
222			"%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
223			test_name, info.si_pid, parent_tid, pidfd,
224			strerror(errno));
225
226	ret = sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
227	if (ret < 0)
228		ksft_exit_fail_msg(
229			"%s test: failed to send SIGKILL to process with pid %d and pidfd %d: %s\n",
230			test_name, parent_tid, pidfd, strerror(errno));
231
232	ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
233	if (ret < 0)
234		ksft_exit_fail_msg(
235			"%s test: failed to wait on WEXITED process with pid %d and pidfd %d: %s\n",
236			test_name, parent_tid, pidfd, strerror(errno));
237
238	if (info.si_signo != SIGCHLD)
239		ksft_exit_fail_msg(
240			"%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
241			test_name, info.si_signo, parent_tid, pidfd,
242			strerror(errno));
243
244	if (info.si_code != CLD_KILLED)
245		ksft_exit_fail_msg(
246			"%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
247			test_name, info.si_code, parent_tid, pidfd,
248			strerror(errno));
249
250	if (info.si_pid != parent_tid)
251		ksft_exit_fail_msg(
252			"%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
253			test_name, info.si_pid, parent_tid, pidfd,
254			strerror(errno));
255
256	close(pidfd);
257
258	ksft_test_result_pass("%s test: Passed\n", test_name);
259	return 0;
260}
261
262int main(int argc, char **argv)
263{
264	ksft_print_header();
265	ksft_set_plan(2);
266
267	test_pidfd_wait_simple();
268	test_pidfd_wait_states();
269
270	return ksft_exit_pass();
271}