diff options
-rw-r--r-- | base/process_util.h | 8 | ||||
-rw-r--r-- | base/process_util_posix.cc | 19 | ||||
-rw-r--r-- | base/process_util_win.cc | 18 | ||||
-rw-r--r-- | chrome/test/test_launcher/out_of_proc_test_runner.cc | 17 |
4 files changed, 53 insertions, 9 deletions
diff --git a/base/process_util.h b/base/process_util.h index f471ac0..09431db 100644 --- a/base/process_util.h +++ b/base/process_util.h @@ -268,6 +268,14 @@ bool DidProcessCrash(bool* child_exited, ProcessHandle handle); // and closes |handle| in any case. bool WaitForExitCode(ProcessHandle handle, int* exit_code); +// Waits for process to exit. If it did exit within |timeout_milliseconds|, +// then puts the exit code in |exit_code|, closes |handle|, and returns true. +// In POSIX systems, if the process has been signaled then |exit_code| is set +// to -1. Returns false on failure (the caller is then responsible for closing +// |handle|). +bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, + int64 timeout_milliseconds); + // Wait for all the processes based on the named executable to exit. If filter // is non-null, then only processes selected by the filter are waited on. // Returns after all processes have exited or wait_milliseconds have expired. diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc index e9f2990..7dc0589 100644 --- a/base/process_util_posix.cc +++ b/base/process_util_posix.cc @@ -689,6 +689,25 @@ bool WaitForExitCode(ProcessHandle handle, int* exit_code) { return false; } +bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, + int64 timeout_milliseconds) { + bool waitpid_success = false; + int status = WaitpidWithTimeout(handle, timeout_milliseconds, + &waitpid_success); + if (status == -1) + return false; + if (!waitpid_success) + return false; + if (!WIFEXITED(status)) + return false; + if (WIFSIGNALED(status)) { + *exit_code = -1; + return true; + } + *exit_code = WEXITSTATUS(status); + return true; +} + bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) { bool waitpid_success; int status; diff --git a/base/process_util_win.cc b/base/process_util_win.cc index 8f08c1c..05d3d60 100644 --- a/base/process_util_win.cc +++ b/base/process_util_win.cc @@ -348,14 +348,24 @@ bool DidProcessCrash(bool* child_exited, ProcessHandle handle) { } bool WaitForExitCode(ProcessHandle handle, int* exit_code) { - ScopedHandle closer(handle); // Ensure that we always close the handle. - if (::WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) { - NOTREACHED(); + bool success = WaitForExitCodeWithTimeout(handle, exit_code, INFINITE); + if (!success) + CloseProcessHandle(handle); + return success; +} + +bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code, + int64 timeout_milliseconds) { + if (::WaitForSingleObject(handle, timeout_milliseconds) != WAIT_OBJECT_0) return false; - } DWORD temp_code; // Don't clobber out-parameters in case of failure. if (!::GetExitCodeProcess(handle, &temp_code)) return false; + + // Only close the handle on success, to give the caller a chance to forcefully + // terminate the process if he wants to. + CloseProcessHandle(handle); + *exit_code = temp_code; return true; } diff --git a/chrome/test/test_launcher/out_of_proc_test_runner.cc b/chrome/test/test_launcher/out_of_proc_test_runner.cc index 98bdeca..4d929a9 100644 --- a/chrome/test/test_launcher/out_of_proc_test_runner.cc +++ b/chrome/test/test_launcher/out_of_proc_test_runner.cc @@ -24,6 +24,8 @@ const char kSingleProcessAltFlag[] = "single_process"; const char kChildProcessFlag[] = "child"; const char kHelpFlag[] = "help"; +const int64 kTestTimeoutMs = 30000; + class OutOfProcTestRunner : public tests::TestRunner { public: OutOfProcTestRunner() { @@ -53,14 +55,19 @@ class OutOfProcTestRunner : public tests::TestRunner { new_cmd_line.AppendSwitch(kChildProcessFlag); base::ProcessHandle process_handle; - bool r = base::LaunchApp(new_cmd_line, false, false, &process_handle); - if (!r) + if (!base::LaunchApp(new_cmd_line, false, false, &process_handle)) return false; int exit_code = 0; - r = base::WaitForExitCode(process_handle, &exit_code); - if (!r) - return false; + if (!base::WaitForExitCodeWithTimeout(process_handle, &exit_code, + kTestTimeoutMs)) { + LOG(ERROR) << "Test timeout exceeded!"; + + exit_code = -1; // Set a non-zero exit code to signal a failure. + + // Ensure that the process terminates. + base::KillProcess(process_handle, -1, true); + } return exit_code == 0; } |