From 4b07d73f4e683d85546d78793a9914a4b5d3d98e Mon Sep 17 00:00:00 2001 From: vladlosev Date: Fri, 9 Sep 2011 05:42:09 +0000 Subject: Ignore SIGPROF signal during clone()/fork() call. clone()/fork() call hangs permanently if it consumes more cpu than the SIGPROF signal timer interval (by Nabeel Mian). --- src/gtest-death-test.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src') diff --git a/src/gtest-death-test.cc b/src/gtest-death-test.cc index fb4a9f9d..2f0b0e38 100644 --- a/src/gtest-death-test.cc +++ b/src/gtest-death-test.cc @@ -43,6 +43,11 @@ # include # include # include + +# if GTEST_OS_LINUX +# include +# endif // GTEST_OS_LINUX + # include # if GTEST_OS_WINDOWS @@ -998,6 +1003,18 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); # else // GTEST_OS_QNX +# if GTEST_OS_LINUX + // When a SIGPROF signal is received while fork() or clone() are executing, + // the process may hang. To avoid this, we ignore SIGPROF here and re-enable + // it after the call to fork()/clone() is complete. + struct sigaction saved_sigprof_action; + struct sigaction ignore_sigprof_action; + memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); + sigemptyset(&ignore_sigprof_action.sa_mask); + ignore_sigprof_action.sa_handler = SIG_IGN; + GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( + SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); +# endif // GTEST_OS_LINUX # if GTEST_HAS_CLONE const bool use_fork = GTEST_FLAG(death_test_use_fork); @@ -1025,6 +1042,10 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { _exit(0); } # endif // GTEST_OS_QNX +# if GTEST_OS_LINUX + GTEST_DEATH_TEST_CHECK_SYSCALL_( + sigaction(SIGPROF, &saved_sigprof_action, NULL)); +# endif // GTEST_OS_LINUX GTEST_DEATH_TEST_CHECK_(child_pid != -1); return child_pid; -- cgit v1.2.3