summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/process_util.h8
-rw-r--r--base/process_util_posix.cc19
-rw-r--r--base/process_util_win.cc18
-rw-r--r--chrome/test/test_launcher/out_of_proc_test_runner.cc17
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;
}