brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · 7eeefa4 Raw
174 lines · cpp
1//===-- Unittests for fork ------------------------------------------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "src/__support/OSUtil/syscall.h"10#include "src/pthread/pthread_atfork.h"11#include "src/signal/raise.h"12#include "src/stdlib/exit.h"13#include "src/sys/wait/wait.h"14#include "src/sys/wait/wait4.h"15#include "src/sys/wait/waitpid.h"16#include "src/unistd/fork.h"17#include "src/unistd/gettid.h"18 19#include "test/IntegrationTest/test.h"20 21#include <signal.h>22#include <sys/syscall.h>23#include <sys/wait.h>24#include <unistd.h>25 26// The tests wait4 and waitpid are present as tests for those functions27// really and not for the fork function. They are here along with the tests28// for fork because it is convenient to invoke and test them after forking29// a child.30 31void fork_and_wait_normal_exit() {32  pid_t pid = LIBC_NAMESPACE::fork();33  if (pid == 0)34    return; // Just end without any thing special.35  ASSERT_TRUE(pid > 0);36  int status;37  pid_t cpid = LIBC_NAMESPACE::wait(&status);38  ASSERT_TRUE(cpid > 0);39  ASSERT_EQ(cpid, pid);40  ASSERT_TRUE(WIFEXITED(status));41}42 43void fork_and_wait4_normal_exit() {44  pid_t pid = LIBC_NAMESPACE::fork();45  if (pid == 0)46    return; // Just end without any thing special.47  ASSERT_TRUE(pid > 0);48  int status;49  struct rusage usage;50  usage.ru_utime = {0, 0};51  usage.ru_stime = {0, 0};52  pid_t cpid = LIBC_NAMESPACE::wait4(pid, &status, 0, &usage);53  ASSERT_TRUE(cpid > 0);54  ASSERT_EQ(cpid, pid);55  ASSERT_TRUE(WIFEXITED(status));56}57 58void fork_and_waitpid_normal_exit() {59  pid_t pid = LIBC_NAMESPACE::fork();60  if (pid == 0)61    return; // Just end without any thing special.62  ASSERT_TRUE(pid > 0);63  int status;64  pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);65  ASSERT_TRUE(cpid > 0);66  ASSERT_EQ(cpid, pid);67  ASSERT_TRUE(WIFEXITED(status));68}69 70void fork_and_wait_signal_exit() {71  pid_t pid = LIBC_NAMESPACE::fork();72  if (pid == 0)73    LIBC_NAMESPACE::raise(SIGUSR1);74  ASSERT_TRUE(pid > 0);75  int status;76  pid_t cpid = LIBC_NAMESPACE::wait(&status);77  ASSERT_TRUE(cpid > 0);78  ASSERT_EQ(cpid, pid);79  ASSERT_FALSE(WIFEXITED(status));80  ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);81}82 83void fork_and_wait4_signal_exit() {84  pid_t pid = LIBC_NAMESPACE::fork();85  if (pid == 0)86    LIBC_NAMESPACE::raise(SIGUSR1);87  ASSERT_TRUE(pid > 0);88  int status;89  struct rusage usage;90  usage.ru_utime = {0, 0};91  usage.ru_stime = {0, 0};92  pid_t cpid = LIBC_NAMESPACE::wait4(pid, &status, 0, &usage);93  ASSERT_TRUE(cpid > 0);94  ASSERT_EQ(cpid, pid);95  ASSERT_FALSE(WIFEXITED(status));96  ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);97}98 99void fork_and_waitpid_signal_exit() {100  pid_t pid = LIBC_NAMESPACE::fork();101  if (pid == 0)102    LIBC_NAMESPACE::raise(SIGUSR1);103  ASSERT_TRUE(pid > 0);104  int status;105  pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);106  ASSERT_TRUE(cpid > 0);107  ASSERT_EQ(cpid, pid);108  ASSERT_FALSE(WIFEXITED(status));109  ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);110}111 112static int prepare = 0;113static int parent = 0;114static int child = 0;115static constexpr int DONE = 0x600D;116 117static void prepare_cb() { prepare = DONE; }118 119static void parent_cb() { parent = DONE; }120 121static void child_cb() { child = DONE; }122 123void fork_with_atfork_callbacks() {124  ASSERT_EQ(LIBC_NAMESPACE::pthread_atfork(&prepare_cb, &parent_cb, &child_cb),125            0);126  pid_t pid = LIBC_NAMESPACE::fork();127  if (pid == 0) {128    // Raise a signal from the child if unexpected at-fork129    // behavior is observed.130    if (child != DONE || prepare != DONE || parent == DONE)131      LIBC_NAMESPACE::raise(SIGUSR1);132    return;133  }134 135  ASSERT_TRUE(pid > 0);136  int status;137  pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);138  ASSERT_TRUE(cpid > 0);139  ASSERT_EQ(cpid, pid);140  ASSERT_TRUE(WIFEXITED(status));141  ASSERT_EQ(prepare, DONE);142  ASSERT_EQ(parent, DONE);143  ASSERT_NE(child, DONE);144}145 146void gettid_test() {147  // fork and verify tid is consistent with the syscall result.148  int pid = LIBC_NAMESPACE::fork();149  ASSERT_EQ(LIBC_NAMESPACE::gettid(),150            LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_gettid));151  if (pid == 0)152    LIBC_NAMESPACE::exit(0);153  // make sure child process exits normally154  int status;155  pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);156  ASSERT_TRUE(cpid > 0);157  ASSERT_EQ(cpid, pid);158  ASSERT_TRUE(WIFEXITED(status));159  ASSERT_EQ(WEXITSTATUS(status), 0);160}161 162TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,163          [[maybe_unused]] char **envp) {164  gettid_test();165  fork_and_wait_normal_exit();166  fork_and_wait4_normal_exit();167  fork_and_waitpid_normal_exit();168  fork_and_wait_signal_exit();169  fork_and_wait4_signal_exit();170  fork_and_waitpid_signal_exit();171  fork_with_atfork_callbacks();172  return 0;173}174