1 //===-- Unittests for fork ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "src/pthread/pthread_atfork.h"
10 #include "src/signal/raise.h"
11 #include "src/sys/wait/wait.h"
12 #include "src/sys/wait/wait4.h"
13 #include "src/sys/wait/waitpid.h"
14 #include "src/unistd/fork.h"
16 #include "test/IntegrationTest/test.h"
23 // The tests wait4 and waitpid are present as tests for those functions
24 // really and not for the fork function. They are here along with the tests
25 // for fork because it is convenient to invoke and test them after forking
28 void fork_and_wait_normal_exit() {
29 pid_t pid
= LIBC_NAMESPACE::fork();
31 return; // Just end without any thing special.
34 pid_t cpid
= LIBC_NAMESPACE::wait(&status
);
35 ASSERT_TRUE(cpid
> 0);
37 ASSERT_TRUE(WIFEXITED(status
));
40 void fork_and_wait4_normal_exit() {
41 pid_t pid
= LIBC_NAMESPACE::fork();
43 return; // Just end without any thing special.
47 usage
.ru_utime
= {0, 0};
48 usage
.ru_stime
= {0, 0};
49 pid_t cpid
= LIBC_NAMESPACE::wait4(pid
, &status
, 0, &usage
);
50 ASSERT_TRUE(cpid
> 0);
52 ASSERT_TRUE(WIFEXITED(status
));
55 void fork_and_waitpid_normal_exit() {
56 pid_t pid
= LIBC_NAMESPACE::fork();
58 return; // Just end without any thing special.
61 pid_t cpid
= LIBC_NAMESPACE::waitpid(pid
, &status
, 0);
62 ASSERT_TRUE(cpid
> 0);
64 ASSERT_TRUE(WIFEXITED(status
));
67 void fork_and_wait_signal_exit() {
68 pid_t pid
= LIBC_NAMESPACE::fork();
70 LIBC_NAMESPACE::raise(SIGUSR1
);
73 pid_t cpid
= LIBC_NAMESPACE::wait(&status
);
74 ASSERT_TRUE(cpid
> 0);
76 ASSERT_FALSE(WIFEXITED(status
));
77 ASSERT_TRUE(WTERMSIG(status
) == SIGUSR1
);
80 void fork_and_wait4_signal_exit() {
81 pid_t pid
= LIBC_NAMESPACE::fork();
83 LIBC_NAMESPACE::raise(SIGUSR1
);
87 usage
.ru_utime
= {0, 0};
88 usage
.ru_stime
= {0, 0};
89 pid_t cpid
= LIBC_NAMESPACE::wait4(pid
, &status
, 0, &usage
);
90 ASSERT_TRUE(cpid
> 0);
92 ASSERT_FALSE(WIFEXITED(status
));
93 ASSERT_TRUE(WTERMSIG(status
) == SIGUSR1
);
96 void fork_and_waitpid_signal_exit() {
97 pid_t pid
= LIBC_NAMESPACE::fork();
99 LIBC_NAMESPACE::raise(SIGUSR1
);
100 ASSERT_TRUE(pid
> 0);
102 pid_t cpid
= LIBC_NAMESPACE::waitpid(pid
, &status
, 0);
103 ASSERT_TRUE(cpid
> 0);
104 ASSERT_EQ(cpid
, pid
);
105 ASSERT_FALSE(WIFEXITED(status
));
106 ASSERT_TRUE(WTERMSIG(status
) == SIGUSR1
);
109 static int prepare
= 0;
110 static int parent
= 0;
111 static int child
= 0;
112 static constexpr int DONE
= 0x600D;
114 static void prepare_cb() { prepare
= DONE
; }
116 static void parent_cb() { parent
= DONE
; }
118 static void child_cb() { child
= DONE
; }
120 void fork_with_atfork_callbacks() {
121 ASSERT_EQ(LIBC_NAMESPACE::pthread_atfork(&prepare_cb
, &parent_cb
, &child_cb
),
123 pid_t pid
= LIBC_NAMESPACE::fork();
125 // Raise a signal from the child if unexpected at-fork
126 // behavior is observed.
127 if (child
!= DONE
|| prepare
!= DONE
|| parent
== DONE
)
128 LIBC_NAMESPACE::raise(SIGUSR1
);
132 ASSERT_TRUE(pid
> 0);
134 pid_t cpid
= LIBC_NAMESPACE::waitpid(pid
, &status
, 0);
135 ASSERT_TRUE(cpid
> 0);
136 ASSERT_EQ(cpid
, pid
);
137 ASSERT_TRUE(WIFEXITED(status
));
138 ASSERT_EQ(prepare
, DONE
);
139 ASSERT_EQ(parent
, DONE
);
140 ASSERT_NE(child
, DONE
);
143 TEST_MAIN(int argc
, char **argv
, char **envp
) {
144 fork_and_wait_normal_exit();
145 fork_and_wait4_normal_exit();
146 fork_and_waitpid_normal_exit();
147 fork_and_wait_signal_exit();
148 fork_and_wait4_signal_exit();
149 fork_and_waitpid_signal_exit();
150 fork_with_atfork_callbacks();