Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: chrome/installer/setup/setup_singleton.cc

Issue 2292293002: Add installer::SetupSingleton. (Closed)
Patch Set: CR grt #9 Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/installer/setup/setup_singleton.h ('k') | chrome/installer/setup/setup_singleton_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/installer/setup/setup_singleton.cc
diff --git a/chrome/installer/setup/setup_singleton.cc b/chrome/installer/setup/setup_singleton.cc
new file mode 100644
index 0000000000000000000000000000000000000000..de73e9f60c1f258f0e21f60cce659e25a028685e
--- /dev/null
+++ b/chrome/installer/setup/setup_singleton.cc
@@ -0,0 +1,138 @@
+// Copyright 2016 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.
+
+#include "chrome/installer/setup/setup_singleton.h"
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/installer_state.h"
+
+namespace installer {
+
+namespace {
+
+enum SetupSingletonAcquisitionResult {
+ // The setup singleton was acquired successfully.
+ SETUP_SINGLETON_ACQUISITION_SUCCESS = 0,
+ // Acquisition of the exit event mutex timed out.
+ SETUP_SINGLETON_ACQUISITION_EXIT_EVENT_MUTEX_TIMEOUT = 1,
+ // Acquisition of the setup mutex timed out.
+ SETUP_SINGLETON_ACQUISITION_SETUP_MUTEX_TIMEOUT = 2,
+ SETUP_SINGLETON_ACQUISITION_RESULT_COUNT,
+};
+
+void RecordSetupSingletonAcquisitionResultHistogram(
+ SetupSingletonAcquisitionResult result) {
+ UMA_HISTOGRAM_ENUMERATION("Setup.Install.SingletonAcquisitionResult", result,
+ SETUP_SINGLETON_ACQUISITION_RESULT_COUNT);
+}
+
+} // namespace
+
+std::unique_ptr<SetupSingleton> SetupSingleton::Acquire(
+ const base::CommandLine& command_line,
+ const MasterPreferences& master_preferences,
+ InstallationState* original_state,
+ InstallerState* installer_state) {
+ DCHECK(original_state);
+ DCHECK(installer_state);
+
+ const base::string16 sync_primitive_name_suffix(
+ base::SizeTToString16(std::hash<base::FilePath::StringType>()(
+ installer_state->target_path().value())));
+
+ std::unique_ptr<SetupSingleton> setup_singleton(
+ new SetupSingleton(sync_primitive_name_suffix));
+
+ {
+ // Acquire a mutex to ensure that a single call to SetupSingleton::Acquire()
+ // signals |exit_event_| and waits for |setup_mutex_| to be released at a
+ // time.
+ base::win::ScopedHandle exit_event_mutex(::CreateMutex(
+ nullptr, FALSE,
+ (L"Global\\ChromeSetupExitEventMutex_" + sync_primitive_name_suffix)
+ .c_str()));
+ DCHECK(exit_event_mutex.IsValid());
+ ScopedHoldMutex scoped_hold_exit_event_mutex;
+ if (!scoped_hold_exit_event_mutex.Acquire(exit_event_mutex.Get())) {
+ RecordSetupSingletonAcquisitionResultHistogram(
+ SETUP_SINGLETON_ACQUISITION_EXIT_EVENT_MUTEX_TIMEOUT);
+ return nullptr;
+ }
+
+ // Signal |exit_event_|. This causes any call to WaitForInterrupt() on a
+ // SetupSingleton bound to the same Chrome installation to return
+ // immediately.
+ setup_singleton->exit_event_.Signal();
+
+ // Acquire |setup_mutex_|.
+ if (!setup_singleton->scoped_hold_setup_mutex_.Acquire(
+ setup_singleton->setup_mutex_.Get())) {
+ RecordSetupSingletonAcquisitionResultHistogram(
+ SETUP_SINGLETON_ACQUISITION_SETUP_MUTEX_TIMEOUT);
+ return nullptr;
+ }
+ setup_singleton->exit_event_.Reset();
+ }
+
+ // Update |original_state| and |installer_state|.
+ original_state->Initialize();
+ installer_state->Initialize(command_line, master_preferences,
+ *original_state);
+
+ RecordSetupSingletonAcquisitionResultHistogram(
+ SETUP_SINGLETON_ACQUISITION_SUCCESS);
+ return setup_singleton;
+}
+
+SetupSingleton::~SetupSingleton() = default;
+
+bool SetupSingleton::WaitForInterrupt(const base::TimeDelta& max_time) {
+ const bool exit_event_signaled = exit_event_.TimedWait(max_time);
+ return exit_event_signaled;
+}
+
+SetupSingleton::ScopedHoldMutex::ScopedHoldMutex() = default;
+
+SetupSingleton::ScopedHoldMutex::~ScopedHoldMutex() {
+ if (mutex_ != INVALID_HANDLE_VALUE)
+ ::ReleaseMutex(mutex_);
+}
+
+bool SetupSingleton::ScopedHoldMutex::Acquire(HANDLE mutex) {
+ DCHECK_NE(INVALID_HANDLE_VALUE, mutex);
+ DCHECK_EQ(INVALID_HANDLE_VALUE, mutex_);
+
+ const DWORD wait_return_value = ::WaitForSingleObject(
+ mutex,
+ static_cast<DWORD>(base::TimeDelta::FromSeconds(5).InMilliseconds()));
+ if (wait_return_value == WAIT_ABANDONED ||
+ wait_return_value == WAIT_OBJECT_0) {
+ mutex_ = mutex;
+ return true;
+ }
+
+ DPCHECK(wait_return_value != WAIT_FAILED);
+ return false;
+}
+
+SetupSingleton::SetupSingleton(const base::string16& sync_primitive_name_suffix)
+ : setup_mutex_(::CreateMutex(
+ nullptr,
+ FALSE,
+ (L"Global\\ChromeSetupMutex_" + sync_primitive_name_suffix).c_str())),
+ exit_event_(base::win::ScopedHandle(::CreateEvent(
+ nullptr,
+ TRUE,
+ FALSE,
+ (L"Global\\ChromeSetupExitEvent_" + sync_primitive_name_suffix)
+ .c_str()))) {
+ DCHECK(setup_mutex_.IsValid());
+}
+
+} // namespace installer
« no previous file with comments | « chrome/installer/setup/setup_singleton.h ('k') | chrome/installer/setup/setup_singleton_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698