Spawns a child process with the same executable as the current process in a thread-safe manner and instructs it to run the death test. The implementation uses fork(2) + exec. On systems where clone(2) is available, it is used instead, being slightly more thread-safe. On QNX, fork supports only single-threaded environments, so this function uses spawn(2) there instead. The function dies with an
| 8899 | // spawn(2) there instead. The function dies with an error message if |
| 8900 | // anything goes wrong. |
| 8901 | static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { |
| 8902 | ExecDeathTestArgs args = { argv, close_fd }; |
| 8903 | pid_t child_pid = -1; |
| 8904 | |
| 8905 | # if GTEST_OS_QNX |
| 8906 | // Obtains the current directory and sets it to be closed in the child |
| 8907 | // process. |
| 8908 | const int cwd_fd = open(".", O_RDONLY); |
| 8909 | GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); |
| 8910 | GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); |
| 8911 | // We need to execute the test program in the same environment where |
| 8912 | // it was originally invoked. Therefore we change to the original |
| 8913 | // working directory first. |
| 8914 | const char* const original_dir = |
| 8915 | UnitTest::GetInstance()->original_working_dir(); |
| 8916 | // We can safely call chdir() as it's a direct system call. |
| 8917 | if (chdir(original_dir) != 0) { |
| 8918 | DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + |
| 8919 | GetLastErrnoDescription()); |
| 8920 | return EXIT_FAILURE; |
| 8921 | } |
| 8922 | |
| 8923 | int fd_flags; |
| 8924 | // Set close_fd to be closed after spawn. |
| 8925 | GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD)); |
| 8926 | GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, |
| 8927 | fd_flags | FD_CLOEXEC)); |
| 8928 | struct inheritance inherit = {0}; |
| 8929 | // spawn is a system call. |
| 8930 | child_pid = |
| 8931 | spawn(args.argv[0], 0, nullptr, &inherit, args.argv, GetEnviron()); |
| 8932 | // Restores the current working directory. |
| 8933 | GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); |
| 8934 | GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); |
| 8935 | |
| 8936 | # else // GTEST_OS_QNX |
| 8937 | # if GTEST_OS_LINUX |
| 8938 | // When a SIGPROF signal is received while fork() or clone() are executing, |
| 8939 | // the process may hang. To avoid this, we ignore SIGPROF here and re-enable |
| 8940 | // it after the call to fork()/clone() is complete. |
| 8941 | struct sigaction saved_sigprof_action; |
| 8942 | struct sigaction ignore_sigprof_action; |
| 8943 | memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); |
| 8944 | sigemptyset(&ignore_sigprof_action.sa_mask); |
| 8945 | ignore_sigprof_action.sa_handler = SIG_IGN; |
| 8946 | GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( |
| 8947 | SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); |
| 8948 | # endif // GTEST_OS_LINUX |
| 8949 | |
| 8950 | # if GTEST_HAS_CLONE |
| 8951 | const bool use_fork = GTEST_FLAG(death_test_use_fork); |
| 8952 | |
| 8953 | if (!use_fork) { |
| 8954 | static const bool stack_grows_down = StackGrowsDown(); |
| 8955 | const auto stack_size = static_cast<size_t>(getpagesize()); |
| 8956 | // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. |
| 8957 | void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE, |
| 8958 | MAP_ANON | MAP_PRIVATE, -1, 0); |
no test coverage detected