Explicitly stop the ExitCodeWatcher if crashpad fails to initialize

Fix for potential deadlock between crashpad and ExitCodeWatcher during
launch - Bug:1057774. In the case where we fail to fully initialize
crashpad, we need to explicitly stop the ExitCodeWatcher.

Bug: 1057774
Change-Id: I31befef2bf25477d38d78c4d136a76d3aaa3be52
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2087900
Reviewed-by: Bruce Dawson <[email protected]>
Reviewed-by: Sigurður Ásgeirsson <[email protected]>
Reviewed-by: Scott Violet <[email protected]>
Commit-Queue: Mike Rorke <[email protected]>
Cr-Commit-Position: refs/heads/master@{#747767}
diff --git a/components/browser_watcher/exit_code_watcher_win.cc b/components/browser_watcher/exit_code_watcher_win.cc
index 3948243..2e2ef77c 100644
--- a/components/browser_watcher/exit_code_watcher_win.cc
+++ b/components/browser_watcher/exit_code_watcher_win.cc
@@ -4,6 +4,8 @@
 
 #include "components/browser_watcher/exit_code_watcher_win.h"
 
+#include <windows.h>
+
 #include <utility>
 
 #include "base/logging.h"
@@ -15,18 +17,19 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 
-#include <windows.h>
-
 namespace browser_watcher {
 
 const char kBrowserExitCodeHistogramName[] = "Stability.BrowserExitCodes";
 
 ExitCodeWatcher::ExitCodeWatcher()
-    : background_thread_("ExitCodeWatcherThread"), exit_code_(STILL_ACTIVE) {}
-
-ExitCodeWatcher::~ExitCodeWatcher() {
+    : background_thread_("ExitCodeWatcherThread"),
+      exit_code_(STILL_ACTIVE),
+      stop_watching_handle_(CreateEvent(nullptr, TRUE, FALSE, nullptr)) {
+  DCHECK(stop_watching_handle_.IsValid());
 }
 
+ExitCodeWatcher::~ExitCodeWatcher() {}
+
 bool ExitCodeWatcher::Initialize(base::Process process) {
   if (!process.IsValid()) {
     LOG(ERROR) << "Invalid parent handle, can't get parent process ID.";
@@ -69,13 +72,20 @@
   return true;
 }
 
-void ExitCodeWatcher::WaitForExit() {
-  if (!process_.WaitForExit(&exit_code_)) {
-    LOG(ERROR) << "Failed to wait for process.";
-    return;
+void ExitCodeWatcher::StopWatching() {
+  if (stop_watching_handle_.IsValid()) {
+    SetEvent(stop_watching_handle_.Get());
   }
+}
 
-  WriteProcessExitCode(exit_code_);
+void ExitCodeWatcher::WaitForExit() {
+  base::Process::WaitExitStatus wait_result =
+      process_.WaitForExitOrEvent(stop_watching_handle_, &exit_code_);
+  if (wait_result == base::Process::WaitExitStatus::PROCESS_EXITED) {
+    WriteProcessExitCode(exit_code_);
+  } else if (wait_result == base::Process::WaitExitStatus::FAILED) {
+    LOG(ERROR) << "Failed to wait for process exit or stop event";
+  }
 }
 
 bool ExitCodeWatcher::WriteProcessExitCode(int exit_code) {