xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/pidfd_open/pidfd_open04.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
4  * Author: Yang Xu <[email protected]>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Verify that the PIDFD_NONBLOCK flag works with pidfd_open() and
11  * that waitid() with a non-blocking pidfd returns EAGAIN.
12  */
13 
14 #include <unistd.h>
15 #include <sys/wait.h>
16 #include <stdlib.h>
17 #include "tst_test.h"
18 #include "lapi/pidfd.h"
19 
20 #ifndef P_PIDFD
21 #define P_PIDFD  3
22 #endif
23 
24 static int pidfd = -1;
25 
run(void)26 static void run(void)
27 {
28 	int flag, pid, ret;
29 	siginfo_t info;
30 
31 	pid = SAFE_FORK();
32 	if (!pid) {
33 		TST_CHECKPOINT_WAIT(0);
34 		exit(EXIT_SUCCESS);
35 	}
36 
37 	TST_EXP_FD_SILENT(pidfd_open(pid, PIDFD_NONBLOCK),
38 				"pidfd_open(%d,  PIDFD_NONBLOCK)", pid);
39 
40 	pidfd = TST_RET;
41 	flag = SAFE_FCNTL(pidfd, F_GETFL);
42 
43 	if (!(flag & O_NONBLOCK))
44 		tst_brk(TFAIL, "pidfd_open(%d, O_NONBLOCK) didn't set O_NONBLOCK flag", pid);
45 
46 	tst_res(TPASS, "pidfd_open(%d, O_NONBLOCK) sets O_NONBLOCK flag", pid);
47 
48 	TST_EXP_FAIL(waitid(P_PIDFD, pidfd, &info, WEXITED), EAGAIN,
49 			"waitid(P_PIDFD,...,WEXITED)");
50 
51 	TST_CHECKPOINT_WAKE(0);
52 
53 	ret = TST_RETRY_FUNC(waitid(P_PIDFD, pidfd, &info, WEXITED), TST_RETVAL_EQ0);
54 	if (ret == 0) {
55 		tst_res(TPASS, "waitid(P_PIDFD) succeeded after child process terminated");
56 	} else {
57 		tst_res(TFAIL, "waitid(P_PIDFD) failed after child process terminated");
58 		SAFE_WAIT(NULL);
59 	}
60 
61 	SAFE_CLOSE(pidfd);
62 }
63 
setup(void)64 static void setup(void)
65 {
66 	pidfd_open_supported();
67 
68 	TEST(pidfd_open(getpid(), PIDFD_NONBLOCK));
69 	if (TST_RET == -1) {
70 		if (TST_ERR == EINVAL) {
71 			tst_brk(TCONF, "PIDFD_NONBLOCK was supported since linux 5.10");
72 			return;
73 		}
74 		tst_brk(TFAIL | TTERRNO,
75 			"pidfd_open(getpid(),PIDFD_NONBLOCK) failed unexpectedly");
76 	}
77 	SAFE_CLOSE(TST_RET);
78 }
79 
cleanup(void)80 static void cleanup(void)
81 {
82 	if (pidfd > -1)
83 		SAFE_CLOSE(pidfd);
84 }
85 
86 static struct tst_test test = {
87 	.needs_root = 1,
88 	.forks_child = 1,
89 	.needs_checkpoints = 1,
90 	.setup = setup,
91 	.cleanup = cleanup,
92 	.test_all = run,
93 };
94