Message:
Adding QNX support to googletest.
As of QNX 6.5.0, it does not support fork under multithread environment,
so I needed to use spawn(QNX specific system call) instead of fork.
Please review this at http://codereview.appspot.com/4517138/
Affected files:
M include/gtest/internal/gtest-port.h
M src/gtest-death-test.cc
M src/gtest-port.cc
M test/gtest-port_test.cc
Index: test/gtest-port_test.cc
===================================================================
--- test/gtest-port_test.cc (revision 583)
+++ test/gtest-port_test.cc (working copy)
@@ -267,7 +267,7 @@
EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(NULL,
-1));
}
-#if GTEST_OS_MAC
+#if GTEST_OS_MAC || GTEST_OS_QNX
void* ThreadFunc(void* data) {
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data);
pthread_mutex_lock(mutex);
@@ -297,6 +297,7 @@
void* dummy;
ASSERT_EQ(0, pthread_join(thread_id, &dummy));
+#if GTEST_OS_MAC
// MacOS X may not immediately report the updated thread count after
// joining a thread, causing flakiness in this test. To counter that, we
// wait for up to .5 seconds for the OS to report the correct value.
@@ -306,6 +307,7 @@
SleepMilliseconds(100);
}
+#endif // GTEST_OS_MAC
EXPECT_EQ(1U, GetThreadCount());
pthread_mutex_destroy(&mutex);
}
Index: include/gtest/internal/gtest-port.h
===================================================================
--- include/gtest/internal/gtest-port.h (revision 583)
+++ include/gtest/internal/gtest-port.h (working copy)
@@ -92,6 +92,7 @@
// GTEST_OS_MAC - Mac OS X
// GTEST_OS_NACL - Google Native Client (NaCl)
// GTEST_OS_OPENBSD - OpenBSD
+// GTEST_OS_QNX - QNX
// GTEST_OS_SOLARIS - Sun Solaris
// GTEST_OS_SYMBIAN - Symbian
// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
@@ -245,6 +246,8 @@
# define GTEST_OS_NACL 1
#elif defined __OpenBSD__
# define GTEST_OS_OPENBSD 1
+#elif defined __QNX__
+# define GTEST_OS_QNX 1
#endif // __CYGWIN__
// Brings in definitions for functions used in the testing::internal::posix
@@ -420,7 +423,8 @@
//
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
// to your compiler flags.
-# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC ||
GTEST_OS_HPUX)
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC ||
GTEST_OS_HPUX \
+ || GTEST_OS_QNX)
#endif // GTEST_HAS_PTHREAD
#if GTEST_HAS_PTHREAD
@@ -452,8 +456,8 @@
// defining __GNUC__ and friends, but cannot compile GCC's tuple
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
// Feature Pack download, which we cannot assume the user has.
-# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >=
40000)) \
- || _MSC_VER >= 1600
+# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >=
40000) \
+ && !GTEST_OS_QNX) || _MSC_VER >= 1600
# define GTEST_USE_OWN_TR1_TUPLE 0
# else
# define GTEST_USE_OWN_TR1_TUPLE 1
@@ -544,7 +548,7 @@
#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS
|| \
(GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
- GTEST_OS_OPENBSD)
+ GTEST_OS_OPENBSD || GTEST_OS_QNX)
# define GTEST_HAS_DEATH_TEST 1
# include <vector> // NOLINT
#endif
Index: src/gtest-death-test.cc
===================================================================
--- src/gtest-death-test.cc (revision 583)
+++ src/gtest-death-test.cc (working copy)
@@ -52,6 +52,10 @@
# include <sys/wait.h>
# endif // GTEST_OS_WINDOWS
+# if GTEST_OS_QNX
+# include <spawn.h>
+# endif // GTEST_OS_QNX
+
#endif // GTEST_HAS_DEATH_TEST
#include "gtest/gtest-message.h"
@@ -971,7 +975,41 @@
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
}
-# else
+# elif GTEST_OS_QNX
+ const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+ if (!use_fork) {
+ // Obtain current directory and set it to be closed in the child
process
+ const int cwd_fd = open(".", O_RDONLY);
+ GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
+ // We need to execute the test program in the same environment where
+ // it was originally invoked. Therefore we change to the original
+ // working directory first.
+ const char* const original_dir =
+ UnitTest::GetInstance()->original_working_dir();
+ // We can safely call chdir() as it's a direct system call.
+ if (chdir(original_dir) != 0) {
+ DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
+ original_dir,
+ GetLastErrnoDescription().c_str()));
+ return EXIT_FAILURE;
+ }
+
+ int fd_flags;
+ // Set close_fd to be closed after spawn
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(
+ fcntl(close_fd, F_SETFD, fd_flags | FD_CLOEXEC));
+ struct inheritance inherit = {0};
+ // spawn is a system call
+ child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv,
GetEnviron());
+ // Return to the current working directory
+ GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
+ GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
+ }
+
+# else // GTEST_OS_QNX
const bool use_fork = true;
# endif // GTEST_HAS_CLONE
Index: src/gtest-port.cc
===================================================================
--- src/gtest-port.cc (revision 583)
+++ src/gtest-port.cc (working copy)
@@ -51,6 +51,11 @@
# include <mach/vm_map.h>
#endif // GTEST_OS_MAC
+#if GTEST_OS_QNX
+# include <devctl.h>
+# include <sys/procfs.h>
+#endif // GTEST_OS_QNX
+
#include "gtest/gtest-spi.h"
#include "gtest/gtest-message.h"
#include "gtest/internal/gtest-internal.h"
@@ -98,6 +103,26 @@
}
}
+#elif GTEST_OS_QNX
+
+// Returns the number of threads running in the process, or 0 to indicate
that
+// we cannot detect it.
+size_t GetThreadCount() {
+ const int fd = open("/proc/self/as", O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+ procfs_info proc_info;
+ const int status =
+ devctl(fd, DCMD_PROC_INFO, &proc_info, sizeof(proc_info), NULL);
+ close(fd);
+ if (status == EOK) {
+ return static_cast<size_t>(proc_info.num_threads);
+ } else {
+ return 0;
+ }
+}
+
#else
size_t GetThreadCount() {