Skip to content

Commit 105b143

Browse files
author
vladlosev
committed
QNX compatibility patch (by Haruka Iwao).
git-svn-id: http://googletest.googlecode.com/svn/trunk@586 861a406c-534a-0410-8894-cb66d6ee9925
1 parent 4f9248a commit 105b143

File tree

4 files changed

+93
-14
lines changed

4 files changed

+93
-14
lines changed

include/gtest/internal/gtest-port.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
// GTEST_OS_MAC - Mac OS X
9393
// GTEST_OS_NACL - Google Native Client (NaCl)
9494
// GTEST_OS_OPENBSD - OpenBSD
95+
// GTEST_OS_QNX - QNX
9596
// GTEST_OS_SOLARIS - Sun Solaris
9697
// GTEST_OS_SYMBIAN - Symbian
9798
// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
@@ -245,6 +246,8 @@
245246
# define GTEST_OS_NACL 1
246247
#elif defined __OpenBSD__
247248
# define GTEST_OS_OPENBSD 1
249+
#elif defined __QNX__
250+
# define GTEST_OS_QNX 1
248251
#endif // __CYGWIN__
249252

250253
// Brings in definitions for functions used in the testing::internal::posix
@@ -420,7 +423,8 @@
420423
//
421424
// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
422425
// to your compiler flags.
423-
# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX)
426+
# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \
427+
|| GTEST_OS_QNX)
424428
#endif // GTEST_HAS_PTHREAD
425429

426430
#if GTEST_HAS_PTHREAD
@@ -452,8 +456,9 @@
452456
// defining __GNUC__ and friends, but cannot compile GCC's tuple
453457
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
454458
// Feature Pack download, which we cannot assume the user has.
455-
# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \
456-
|| _MSC_VER >= 1600
459+
// QNX's QCC compiler is a modified GCC but it doesn't support TR1 tuple.
460+
# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \
461+
&& !GTEST_OS_QNX) || _MSC_VER >= 1600
457462
# define GTEST_USE_OWN_TR1_TUPLE 0
458463
# else
459464
# define GTEST_USE_OWN_TR1_TUPLE 1
@@ -544,7 +549,7 @@
544549
#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
545550
(GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
546551
GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
547-
GTEST_OS_OPENBSD)
552+
GTEST_OS_OPENBSD || GTEST_OS_QNX)
548553
# define GTEST_HAS_DEATH_TEST 1
549554
# include <vector> // NOLINT
550555
#endif

src/gtest-death-test.cc

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
# include <sys/wait.h>
5353
# endif // GTEST_OS_WINDOWS
5454

55+
# if GTEST_OS_QNX
56+
# include <spawn.h>
57+
# endif // GTEST_OS_QNX
58+
5559
#endif // GTEST_HAS_DEATH_TEST
5660

5761
#include "gtest/gtest-message.h"
@@ -894,6 +898,7 @@ extern "C" char** environ;
894898
inline char** GetEnviron() { return environ; }
895899
# endif // GTEST_OS_MAC
896900

901+
# if !GTEST_OS_QNX
897902
// The main function for a threadsafe-style death test child process.
898903
// This function is called in a clone()-ed process and thus must avoid
899904
// any potentially unsafe operations like malloc or libc functions.
@@ -926,6 +931,7 @@ static int ExecDeathTestChildMain(void* child_arg) {
926931
GetLastErrnoDescription().c_str()));
927932
return EXIT_FAILURE;
928933
}
934+
# endif // !GTEST_OS_QNX
929935

930936
// Two utility routines that together determine the direction the stack
931937
// grows.
@@ -949,14 +955,51 @@ bool StackGrowsDown() {
949955
return result;
950956
}
951957

952-
// A threadsafe implementation of fork(2) for threadsafe-style death tests
953-
// that uses clone(2). It dies with an error message if anything goes
954-
// wrong.
955-
static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
958+
// Spawns a child process with the same executable as the current process in
959+
// a thread-safe manner and instructs it to run the death test. The
960+
// implementation uses fork(2) + exec. On systems where clone(2) is
961+
// available, it is used instead, being slightly more thread-safe. On QNX,
962+
// fork supports only single-threaded environments, so this function uses
963+
// spawn(2) there instead. The function dies with an error message if
964+
// anything goes wrong.
965+
static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
956966
ExecDeathTestArgs args = { argv, close_fd };
957967
pid_t child_pid = -1;
958968

959-
# if GTEST_HAS_CLONE
969+
# if GTEST_OS_QNX
970+
// Obtains the current directory and sets it to be closed in the child
971+
// process.
972+
const int cwd_fd = open(".", O_RDONLY);
973+
GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
974+
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
975+
// We need to execute the test program in the same environment where
976+
// it was originally invoked. Therefore we change to the original
977+
// working directory first.
978+
const char* const original_dir =
979+
UnitTest::GetInstance()->original_working_dir();
980+
// We can safely call chdir() as it's a direct system call.
981+
if (chdir(original_dir) != 0) {
982+
DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
983+
original_dir,
984+
GetLastErrnoDescription().c_str()));
985+
return EXIT_FAILURE;
986+
}
987+
988+
int fd_flags;
989+
// Set close_fd to be closed after spawn.
990+
GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
991+
GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
992+
fd_flags | FD_CLOEXEC));
993+
struct inheritance inherit = {0};
994+
// spawn is a system call.
995+
child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
996+
// Restores the current working directory.
997+
GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
998+
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
999+
1000+
# else // GTEST_OS_QNX
1001+
1002+
# if GTEST_HAS_CLONE
9601003
const bool use_fork = GTEST_FLAG(death_test_use_fork);
9611004

9621005
if (!use_fork) {
@@ -973,14 +1016,15 @@ static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
9731016

9741017
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
9751018
}
976-
# else
1019+
# else
9771020
const bool use_fork = true;
978-
# endif // GTEST_HAS_CLONE
1021+
# endif // GTEST_HAS_CLONE
9791022

9801023
if (use_fork && (child_pid = fork()) == 0) {
9811024
ExecDeathTestChildMain(&args);
9821025
_exit(0);
9831026
}
1027+
# endif // GTEST_OS_QNX
9841028

9851029
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
9861030
return child_pid;
@@ -1028,7 +1072,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
10281072
// is necessary.
10291073
FlushInfoLog();
10301074

1031-
const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
1075+
const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
10321076
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
10331077
set_child_pid(child_pid);
10341078
set_read_fd(pipe_fd[0]);

src/gtest-port.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@
5151
# include <mach/vm_map.h>
5252
#endif // GTEST_OS_MAC
5353

54+
#if GTEST_OS_QNX
55+
# include <devctl.h>
56+
# include <sys/procfs.h>
57+
#endif // GTEST_OS_QNX
58+
5459
#include "gtest/gtest-spi.h"
5560
#include "gtest/gtest-message.h"
5661
#include "gtest/internal/gtest-internal.h"
@@ -98,6 +103,26 @@ size_t GetThreadCount() {
98103
}
99104
}
100105

106+
#elif GTEST_OS_QNX
107+
108+
// Returns the number of threads running in the process, or 0 to indicate that
109+
// we cannot detect it.
110+
size_t GetThreadCount() {
111+
const int fd = open("/proc/self/as", O_RDONLY);
112+
if (fd < 0) {
113+
return 0;
114+
}
115+
procfs_info process_info;
116+
const int status =
117+
devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
118+
close(fd);
119+
if (status == EOK) {
120+
return static_cast<size_t>(process_info.num_threads);
121+
} else {
122+
return 0;
123+
}
124+
}
125+
101126
#else
102127

103128
size_t GetThreadCount() {

test/gtest-port_test.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
267267
EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(NULL, -1));
268268
}
269269

270-
#if GTEST_OS_MAC
270+
#if GTEST_OS_MAC || GTEST_OS_QNX
271271
void* ThreadFunc(void* data) {
272272
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data);
273273
pthread_mutex_lock(mutex);
@@ -297,6 +297,8 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
297297
void* dummy;
298298
ASSERT_EQ(0, pthread_join(thread_id, &dummy));
299299

300+
# if GTEST_OS_MAC
301+
300302
// MacOS X may not immediately report the updated thread count after
301303
// joining a thread, causing flakiness in this test. To counter that, we
302304
// wait for up to .5 seconds for the OS to report the correct value.
@@ -306,14 +308,17 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
306308

307309
SleepMilliseconds(100);
308310
}
311+
312+
# endif // GTEST_OS_MAC
313+
309314
EXPECT_EQ(1U, GetThreadCount());
310315
pthread_mutex_destroy(&mutex);
311316
}
312317
#else
313318
TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
314319
EXPECT_EQ(0U, GetThreadCount());
315320
}
316-
#endif // GTEST_OS_MAC
321+
#endif // GTEST_OS_MAC || GTEST_OS_QNX
317322

318323
TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
319324
const bool a_false_condition = false;

0 commit comments

Comments
 (0)