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