| Index: sandbox/tests/common/controller.cc | 
| =================================================================== | 
| --- sandbox/tests/common/controller.cc	(revision 129865) | 
| +++ sandbox/tests/common/controller.cc	(working copy) | 
| @@ -1,4 +1,4 @@ | 
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| // Use of this source code is governed by a BSD-style license that can be | 
| // found in the LICENSE file. | 
|  | 
| @@ -51,6 +51,13 @@ | 
| return full_path; | 
| } | 
|  | 
| +bool IsProcessRunning(HANDLE process) { | 
| +  DWORD exit_code = 0; | 
| +  if (::GetExitCodeProcess(process, &exit_code)) | 
| +    return exit_code == STILL_ACTIVE; | 
| +  return false; | 
| +} | 
| + | 
| }  // namespace | 
|  | 
| namespace sandbox { | 
| @@ -81,11 +88,13 @@ | 
| } | 
|  | 
| TestRunner::TestRunner(JobLevel job_level, TokenLevel startup_token, | 
| -                       TokenLevel main_token) : is_init_(false) { | 
| +                       TokenLevel main_token) | 
| +    : is_init_(false), is_async_(false), target_process_id_(0) { | 
| Init(job_level, startup_token, main_token); | 
| } | 
|  | 
| -TestRunner::TestRunner() : is_init_(false) { | 
| +TestRunner::TestRunner() | 
| +    : is_init_(false), is_async_(false), target_process_id_(0) { | 
| Init(JOB_LOCKDOWN, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN); | 
| } | 
|  | 
| @@ -95,6 +104,8 @@ | 
| policy_ = NULL; | 
| timeout_ = kDefaultTimeout; | 
| state_ = AFTER_REVERT; | 
| +  is_async_= false; | 
| +  target_process_id_ = 0; | 
|  | 
| broker_ = GetBroker(); | 
| if (!broker_) | 
| @@ -115,6 +126,9 @@ | 
| } | 
|  | 
| TestRunner::~TestRunner() { | 
| +  if (target_process_) | 
| +    ::TerminateProcess(target_process_, 0); | 
| + | 
| if (policy_) | 
| policy_->Release(); | 
| } | 
| @@ -177,6 +191,14 @@ | 
| if (!is_init_) | 
| return SBOX_TEST_FAILED_TO_RUN_TEST; | 
|  | 
| +  // For simplicity TestRunner supports only one process per instance. | 
| +  if (target_process_) { | 
| +    if (IsProcessRunning(target_process_)) | 
| +      return SBOX_TEST_FAILED_TO_RUN_TEST; | 
| +    target_process_.Close(); | 
| +    target_process_id_ = 0; | 
| +  } | 
| + | 
| // Get the path to the sandboxed process. | 
| wchar_t prog_name[MAX_PATH]; | 
| GetModuleFileNameW(NULL, prog_name, MAX_PATH); | 
| @@ -198,6 +220,14 @@ | 
|  | 
| ::ResumeThread(target.hThread); | 
|  | 
| +  // For an asynchronous run we don't bother waiting. | 
| +  if (is_async_) { | 
| +    target_process_.Set(target.hProcess); | 
| +    target_process_id_ = target.dwProcessId; | 
| +    ::CloseHandle(target.hThread); | 
| +    return SBOX_TEST_SUCCEEDED; | 
| +  } | 
| + | 
| if (::IsDebuggerPresent()) { | 
| // Don't kill the target process on a time-out while we are debugging. | 
| timeout_ = INFINITE; | 
|  |