Implement the WindowsLogoffRace finch experiment.

[email protected],[email protected]
[email protected]
BUG=388741

Review URL: https://codereview.chromium.org/385123004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283282 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 27b7c5b..27f05b9 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -15,6 +15,7 @@
 #include "base/debug/alias.h"
 #include "base/debug/leak_annotations.h"
 #include "base/files/file_path.h"
+#include "base/metrics/field_trial.h"
 #include "base/path_service.h"
 #include "base/prefs/json_pref_store.h"
 #include "base/prefs/pref_registry_simple.h"
@@ -441,9 +442,25 @@
   return waitable_event_.TimedWait(max_time);
 }
 
+bool ExperimentUseBrokenSynchronization() {
+  // The logoff behavior used to have a race, whereby it would perform profile
+  // IO writes on the blocking thread pool, but would sycnhronize to the FILE
+  // thread. Windows feels free to terminate any process that's hidden or
+  // destroyed all it's windows, and sometimes Chrome would be terminated
+  // with pending profile IO due to this mis-synchronization.
+  // Under the "WindowsLogoffRace" experiment group, the broken behavior is
+  // emulated, in order to allow measuring what fraction of unclean shutdowns
+  // are due to this bug.
+  const std::string group_name =
+      base::FieldTrialList::FindFullName("WindowsLogoffRace");
+  return group_name == "BrokenSynchronization";
+}
+
 }  // namespace
 
 void BrowserProcessImpl::EndSession() {
+  bool use_broken_synchronization = ExperimentUseBrokenSynchronization();
+
   // Mark all the profiles as clean.
   ProfileManager* pm = profile_manager();
   std::vector<Profile*> profiles(pm->GetLoadedProfiles());
@@ -452,7 +469,8 @@
     Profile* profile = profiles[i];
     profile->SetExitType(Profile::EXIT_SESSION_ENDED);
 
-    rundown_counter->Post(profile->GetIOTaskRunner());
+    if (!use_broken_synchronization)
+      rundown_counter->Post(profile->GetIOTaskRunner());
   }
 
   // Tell the metrics service it was cleanly shutdown.
@@ -465,7 +483,8 @@
     // commit metrics::prefs::kStabilitySessionEndCompleted change immediately.
     local_state()->CommitPendingWrite();
 
-    rundown_counter->Post(local_state_task_runner_);
+    if (!use_broken_synchronization)
+      rundown_counter->Post(local_state_task_runner_);
 #endif
   }
 
@@ -479,6 +498,11 @@
   // If you change the condition here, be sure to also change
   // ProfileBrowserTests to match.
 #if defined(USE_X11) || defined(OS_WIN)
+  if (use_broken_synchronization) {
+    rundown_counter->Post(
+        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
+  }
+
   // Do a best-effort wait on the successful countdown of rundown tasks. Note
   // that if we don't complete "quickly enough", Windows will terminate our
   // process.