MCPcopy Create free account
hub / github.com/awslabs/aws-lambda-cpp / ExecDeathTestSpawnChild

Function ExecDeathTestSpawnChild

tests/gtest/gtest-all.cc:8901–8995  ·  view source on GitHub ↗

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

Source from the content-addressed store, hash-verified

8899// spawn(2) there instead. The function dies with an error message if
8900// anything goes wrong.
8901static 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);

Callers 1

AssumeRoleMethod · 0.85

Calls 7

DeathTestAbortFunction · 0.85
GetLastErrnoDescriptionFunction · 0.85
GetEnvironFunction · 0.85
StackGrowsDownFunction · 0.85
ExecDeathTestChildMainFunction · 0.85
original_working_dirMethod · 0.80
sigactionClass · 0.70

Tested by

no test coverage detected