summaryrefslogtreecommitdiffstats
path: root/src/gtest-death-test.cc
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2009-03-17 21:03:35 (GMT)
committerzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2009-03-17 21:03:35 (GMT)
commit9623aed82cf3e0dcd2fb2fb7442a5a9507ac55a5 (patch)
tree546adb028be5895120f443878b06482c68f96dfc /src/gtest-death-test.cc
parent62f8d28c0bd5cb057013fdf5b366db7b7981ec4c (diff)
downloadgoogletest-9623aed82cf3e0dcd2fb2fb7442a5a9507ac55a5.zip
googletest-9623aed82cf3e0dcd2fb2fb7442a5a9507ac55a5.tar.gz
googletest-9623aed82cf3e0dcd2fb2fb7442a5a9507ac55a5.tar.bz2
Enables death tests on Cygwin and Mac (by Vlad Losev); fixes a python test on Mac.
Diffstat (limited to 'src/gtest-death-test.cc')
-rw-r--r--src/gtest-death-test.cc73
1 files changed, 52 insertions, 21 deletions
diff --git a/src/gtest-death-test.cc b/src/gtest-death-test.cc
index d969586..7e7dd60 100644
--- a/src/gtest-death-test.cc
+++ b/src/gtest-death-test.cc
@@ -35,6 +35,11 @@
#include <gtest/internal/gtest-port.h>
#if GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_MAC
+#include <crt_externs.h>
+#endif // GTEST_OS_MAC
+
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -44,6 +49,7 @@
#include <windows.h>
#else
#include <sys/mman.h>
+#include <sys/wait.h>
#endif // GTEST_OS_WINDOWS
#endif // GTEST_HAS_DEATH_TEST
@@ -80,8 +86,9 @@ GTEST_DEFINE_bool_(
death_test_use_fork,
internal::BoolFromGTestEnv("death_test_use_fork", false),
"Instructs to use fork()/_exit() instead of clone() in death tests. "
- "Useful when running under valgrind or similar tools if those "
- "do not support clone(). Valgrind 3.3.1 will just fail if "
+ "Ignored and always uses fork() on POSIX systems where clone() is not "
+ "implemented. Useful when running under valgrind or similar tools if "
+ "those do not support clone(). Valgrind 3.3.1 will just fail if "
"it sees an unsupported combination of clone() flags. "
"It is not recommended to use this flag w/o valgrind though it will "
"work in 99% of the cases. Once valgrind is fixed, this flag will "
@@ -963,6 +970,22 @@ struct ExecDeathTestArgs {
int close_fd; // File descriptor to close; the read end of a pipe
};
+#if GTEST_OS_MAC
+inline char** GetEnviron() {
+ // When Google Test is built as a framework on MacOS X, the environ variable
+ // is unavailable. Apple's documentation (man environ) recommends using
+ // _NSGetEnviron() instead.
+ return *_NSGetEnviron();
+}
+#else
+extern "C" char** environ; // Some POSIX platforms expect you
+ // to declare environ. extern "C" makes
+ // it reside in the global namespace.
+inline char** GetEnviron() {
+ return environ;
+}
+#endif // GTEST_OS_MAC
+
// The main function for a threadsafe-style death test child process.
// This function is called in a clone()-ed process and thus must avoid
// any potentially unsafe operations like malloc or libc functions.
@@ -988,7 +1011,7 @@ static int ExecDeathTestChildMain(void* child_arg) {
// unsafe. Since execve() doesn't search the PATH, the user must
// invoke the test program via a valid path that contains at least
// one path separator.
- execve(args->argv[0], args->argv, environ);
+ execve(args->argv[0], args->argv, GetEnviron());
DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s",
args->argv[0],
original_dir,
@@ -1001,12 +1024,12 @@ static int ExecDeathTestChildMain(void* child_arg) {
// This could be accomplished more elegantly by a single recursive
// function, but we want to guard against the unlikely possibility of
// a smart compiler optimizing the recursion away.
-static bool StackLowerThanAddress(const void* ptr) {
+bool StackLowerThanAddress(const void* ptr) {
int dummy;
return &dummy < ptr;
}
-static bool StackGrowsDown() {
+bool StackGrowsDown() {
int dummy;
return StackLowerThanAddress(&dummy);
}
@@ -1015,28 +1038,36 @@ static bool StackGrowsDown() {
// that uses clone(2). It dies with an error message if anything goes
// wrong.
static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
- static const bool stack_grows_down = StackGrowsDown();
- const size_t stack_size = getpagesize();
- void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
- MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
- void* const stack_top =
- static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0);
ExecDeathTestArgs args = { argv, close_fd };
pid_t child_pid;
- if (GTEST_FLAG(death_test_use_fork)) {
- // Valgrind-friendly version. As of valgrind 3.3.1 the clone() call below
- // is not supported (valgrind will fail with an error message).
- if ((child_pid = fork()) == 0) {
+
+#if GTEST_HAS_CLONE
+ const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+ if (!use_fork) {
+ static const bool stack_grows_down = StackGrowsDown();
+ const size_t stack_size = getpagesize();
+ // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+ void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+ void* const stack_top =
+ static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0);
+
+ child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+ GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+ }
+#else
+ const bool use_fork = true;
+#endif // GTEST_HAS_CLONE
+
+ if (use_fork && (child_pid = fork()) == 0) {
ExecDeathTestChildMain(&args);
_exit(0);
- }
- } else {
- child_pid = clone(&ExecDeathTestChildMain, stack_top,
- SIGCHLD, &args);
}
+
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
- GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
return child_pid;
}