xref: /llvm-project/libc/test/integration/src/unistd/fork_test.cpp (revision 46944b0cbc9a9d8daad0182c40fcd3560bc9ca35)
1e3638e83SSiva Chandra Reddy //===-- Unittests for fork ------------------------------------------------===//
2e3638e83SSiva Chandra Reddy //
3e3638e83SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e3638e83SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5e3638e83SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e3638e83SSiva Chandra Reddy //
7e3638e83SSiva Chandra Reddy //===----------------------------------------------------------------------===//
8e3638e83SSiva Chandra Reddy 
9*301db3deSSchrodinger ZHU Yifan #include "src/__support/OSUtil/syscall.h"
10438e5918SSiva Chandra Reddy #include "src/pthread/pthread_atfork.h"
11e3638e83SSiva Chandra Reddy #include "src/signal/raise.h"
12*301db3deSSchrodinger ZHU Yifan #include "src/stdlib/exit.h"
13e3638e83SSiva Chandra Reddy #include "src/sys/wait/wait.h"
14995105deSSiva Chandra Reddy #include "src/sys/wait/wait4.h"
15995105deSSiva Chandra Reddy #include "src/sys/wait/waitpid.h"
16e3638e83SSiva Chandra Reddy #include "src/unistd/fork.h"
17*301db3deSSchrodinger ZHU Yifan #include "src/unistd/gettid.h"
183db5c1eeSSchrodinger ZHU Yifan 
19af1315c2SSiva Chandra Reddy #include "test/IntegrationTest/test.h"
20e3638e83SSiva Chandra Reddy 
21e3638e83SSiva Chandra Reddy #include <signal.h>
22*301db3deSSchrodinger ZHU Yifan #include <sys/syscall.h>
23e3638e83SSiva Chandra Reddy #include <sys/wait.h>
24e3638e83SSiva Chandra Reddy #include <unistd.h>
25e3638e83SSiva Chandra Reddy 
26995105deSSiva Chandra Reddy // The tests wait4 and waitpid are present as tests for those functions
27995105deSSiva Chandra Reddy // really and not for the fork function. They are here along with the tests
28995105deSSiva Chandra Reddy // for fork because it is convenient to invoke and test them after forking
29995105deSSiva Chandra Reddy // a child.
30995105deSSiva Chandra Reddy 
31e3638e83SSiva Chandra Reddy void fork_and_wait_normal_exit() {
32b6bc9d72SGuillaume Chatelet   pid_t pid = LIBC_NAMESPACE::fork();
33e3638e83SSiva Chandra Reddy   if (pid == 0)
34e3638e83SSiva Chandra Reddy     return; // Just end without any thing special.
35e3638e83SSiva Chandra Reddy   ASSERT_TRUE(pid > 0);
36e3638e83SSiva Chandra Reddy   int status;
37b6bc9d72SGuillaume Chatelet   pid_t cpid = LIBC_NAMESPACE::wait(&status);
38e3638e83SSiva Chandra Reddy   ASSERT_TRUE(cpid > 0);
39e3638e83SSiva Chandra Reddy   ASSERT_EQ(cpid, pid);
40e3638e83SSiva Chandra Reddy   ASSERT_TRUE(WIFEXITED(status));
41e3638e83SSiva Chandra Reddy }
42e3638e83SSiva Chandra Reddy 
43995105deSSiva Chandra Reddy void fork_and_wait4_normal_exit() {
44b6bc9d72SGuillaume Chatelet   pid_t pid = LIBC_NAMESPACE::fork();
45995105deSSiva Chandra Reddy   if (pid == 0)
46995105deSSiva Chandra Reddy     return; // Just end without any thing special.
47995105deSSiva Chandra Reddy   ASSERT_TRUE(pid > 0);
48995105deSSiva Chandra Reddy   int status;
49995105deSSiva Chandra Reddy   struct rusage usage;
50995105deSSiva Chandra Reddy   usage.ru_utime = {0, 0};
51995105deSSiva Chandra Reddy   usage.ru_stime = {0, 0};
52b6bc9d72SGuillaume Chatelet   pid_t cpid = LIBC_NAMESPACE::wait4(pid, &status, 0, &usage);
53995105deSSiva Chandra Reddy   ASSERT_TRUE(cpid > 0);
54995105deSSiva Chandra Reddy   ASSERT_EQ(cpid, pid);
55995105deSSiva Chandra Reddy   ASSERT_TRUE(WIFEXITED(status));
56995105deSSiva Chandra Reddy }
57995105deSSiva Chandra Reddy 
58995105deSSiva Chandra Reddy void fork_and_waitpid_normal_exit() {
59b6bc9d72SGuillaume Chatelet   pid_t pid = LIBC_NAMESPACE::fork();
60995105deSSiva Chandra Reddy   if (pid == 0)
61995105deSSiva Chandra Reddy     return; // Just end without any thing special.
62995105deSSiva Chandra Reddy   ASSERT_TRUE(pid > 0);
63995105deSSiva Chandra Reddy   int status;
64b6bc9d72SGuillaume Chatelet   pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);
65995105deSSiva Chandra Reddy   ASSERT_TRUE(cpid > 0);
66995105deSSiva Chandra Reddy   ASSERT_EQ(cpid, pid);
67995105deSSiva Chandra Reddy   ASSERT_TRUE(WIFEXITED(status));
68995105deSSiva Chandra Reddy }
69995105deSSiva Chandra Reddy 
70e3638e83SSiva Chandra Reddy void fork_and_wait_signal_exit() {
71b6bc9d72SGuillaume Chatelet   pid_t pid = LIBC_NAMESPACE::fork();
72e3638e83SSiva Chandra Reddy   if (pid == 0)
73b6bc9d72SGuillaume Chatelet     LIBC_NAMESPACE::raise(SIGUSR1);
74e3638e83SSiva Chandra Reddy   ASSERT_TRUE(pid > 0);
75e3638e83SSiva Chandra Reddy   int status;
76b6bc9d72SGuillaume Chatelet   pid_t cpid = LIBC_NAMESPACE::wait(&status);
77e3638e83SSiva Chandra Reddy   ASSERT_TRUE(cpid > 0);
78e3638e83SSiva Chandra Reddy   ASSERT_EQ(cpid, pid);
79e3638e83SSiva Chandra Reddy   ASSERT_FALSE(WIFEXITED(status));
80e3638e83SSiva Chandra Reddy   ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);
81e3638e83SSiva Chandra Reddy }
82e3638e83SSiva Chandra Reddy 
83995105deSSiva Chandra Reddy void fork_and_wait4_signal_exit() {
84b6bc9d72SGuillaume Chatelet   pid_t pid = LIBC_NAMESPACE::fork();
85995105deSSiva Chandra Reddy   if (pid == 0)
86b6bc9d72SGuillaume Chatelet     LIBC_NAMESPACE::raise(SIGUSR1);
87995105deSSiva Chandra Reddy   ASSERT_TRUE(pid > 0);
88995105deSSiva Chandra Reddy   int status;
89995105deSSiva Chandra Reddy   struct rusage usage;
90995105deSSiva Chandra Reddy   usage.ru_utime = {0, 0};
91995105deSSiva Chandra Reddy   usage.ru_stime = {0, 0};
92b6bc9d72SGuillaume Chatelet   pid_t cpid = LIBC_NAMESPACE::wait4(pid, &status, 0, &usage);
93995105deSSiva Chandra Reddy   ASSERT_TRUE(cpid > 0);
94995105deSSiva Chandra Reddy   ASSERT_EQ(cpid, pid);
95995105deSSiva Chandra Reddy   ASSERT_FALSE(WIFEXITED(status));
96995105deSSiva Chandra Reddy   ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);
97995105deSSiva Chandra Reddy }
98995105deSSiva Chandra Reddy 
99995105deSSiva Chandra Reddy void fork_and_waitpid_signal_exit() {
100b6bc9d72SGuillaume Chatelet   pid_t pid = LIBC_NAMESPACE::fork();
101995105deSSiva Chandra Reddy   if (pid == 0)
102b6bc9d72SGuillaume Chatelet     LIBC_NAMESPACE::raise(SIGUSR1);
103995105deSSiva Chandra Reddy   ASSERT_TRUE(pid > 0);
104995105deSSiva Chandra Reddy   int status;
105b6bc9d72SGuillaume Chatelet   pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);
106995105deSSiva Chandra Reddy   ASSERT_TRUE(cpid > 0);
107995105deSSiva Chandra Reddy   ASSERT_EQ(cpid, pid);
108995105deSSiva Chandra Reddy   ASSERT_FALSE(WIFEXITED(status));
109995105deSSiva Chandra Reddy   ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);
110995105deSSiva Chandra Reddy }
111995105deSSiva Chandra Reddy 
112438e5918SSiva Chandra Reddy static int prepare = 0;
113438e5918SSiva Chandra Reddy static int parent = 0;
114438e5918SSiva Chandra Reddy static int child = 0;
115438e5918SSiva Chandra Reddy static constexpr int DONE = 0x600D;
116438e5918SSiva Chandra Reddy 
117438e5918SSiva Chandra Reddy static void prepare_cb() { prepare = DONE; }
118438e5918SSiva Chandra Reddy 
119438e5918SSiva Chandra Reddy static void parent_cb() { parent = DONE; }
120438e5918SSiva Chandra Reddy 
121438e5918SSiva Chandra Reddy static void child_cb() { child = DONE; }
122438e5918SSiva Chandra Reddy 
123438e5918SSiva Chandra Reddy void fork_with_atfork_callbacks() {
124b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::pthread_atfork(&prepare_cb, &parent_cb, &child_cb),
125b6bc9d72SGuillaume Chatelet             0);
126b6bc9d72SGuillaume Chatelet   pid_t pid = LIBC_NAMESPACE::fork();
127438e5918SSiva Chandra Reddy   if (pid == 0) {
128438e5918SSiva Chandra Reddy     // Raise a signal from the child if unexpected at-fork
129438e5918SSiva Chandra Reddy     // behavior is observed.
130438e5918SSiva Chandra Reddy     if (child != DONE || prepare != DONE || parent == DONE)
131b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::raise(SIGUSR1);
132438e5918SSiva Chandra Reddy     return;
133438e5918SSiva Chandra Reddy   }
134438e5918SSiva Chandra Reddy 
135438e5918SSiva Chandra Reddy   ASSERT_TRUE(pid > 0);
136438e5918SSiva Chandra Reddy   int status;
137b6bc9d72SGuillaume Chatelet   pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);
138438e5918SSiva Chandra Reddy   ASSERT_TRUE(cpid > 0);
139438e5918SSiva Chandra Reddy   ASSERT_EQ(cpid, pid);
140438e5918SSiva Chandra Reddy   ASSERT_TRUE(WIFEXITED(status));
141438e5918SSiva Chandra Reddy   ASSERT_EQ(prepare, DONE);
142438e5918SSiva Chandra Reddy   ASSERT_EQ(parent, DONE);
143438e5918SSiva Chandra Reddy   ASSERT_NE(child, DONE);
144438e5918SSiva Chandra Reddy }
145438e5918SSiva Chandra Reddy 
146*301db3deSSchrodinger ZHU Yifan void gettid_test() {
147*301db3deSSchrodinger ZHU Yifan   // fork and verify tid is consistent with the syscall result.
148*301db3deSSchrodinger ZHU Yifan   int pid = LIBC_NAMESPACE::fork();
149*301db3deSSchrodinger ZHU Yifan   ASSERT_EQ(LIBC_NAMESPACE::gettid(),
150*301db3deSSchrodinger ZHU Yifan             LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_gettid));
151*301db3deSSchrodinger ZHU Yifan   if (pid == 0)
152*301db3deSSchrodinger ZHU Yifan     LIBC_NAMESPACE::exit(0);
153*301db3deSSchrodinger ZHU Yifan   // make sure child process exits normally
154*301db3deSSchrodinger ZHU Yifan   int status;
155*301db3deSSchrodinger ZHU Yifan   pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);
156*301db3deSSchrodinger ZHU Yifan   ASSERT_TRUE(cpid > 0);
157*301db3deSSchrodinger ZHU Yifan   ASSERT_EQ(cpid, pid);
158*301db3deSSchrodinger ZHU Yifan   ASSERT_TRUE(WIFEXITED(status));
159*301db3deSSchrodinger ZHU Yifan   ASSERT_EQ(WEXITSTATUS(status), 0);
160*301db3deSSchrodinger ZHU Yifan }
161*301db3deSSchrodinger ZHU Yifan 
162e3638e83SSiva Chandra Reddy TEST_MAIN(int argc, char **argv, char **envp) {
163*301db3deSSchrodinger ZHU Yifan   gettid_test();
164e3638e83SSiva Chandra Reddy   fork_and_wait_normal_exit();
165995105deSSiva Chandra Reddy   fork_and_wait4_normal_exit();
166995105deSSiva Chandra Reddy   fork_and_waitpid_normal_exit();
167e3638e83SSiva Chandra Reddy   fork_and_wait_signal_exit();
168995105deSSiva Chandra Reddy   fork_and_wait4_signal_exit();
169995105deSSiva Chandra Reddy   fork_and_waitpid_signal_exit();
170438e5918SSiva Chandra Reddy   fork_with_atfork_callbacks();
171e3638e83SSiva Chandra Reddy   return 0;
172e3638e83SSiva Chandra Reddy }
173