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

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

Issue 2292293002: Add installer::SetupSingleton. (Closed)
Patch Set: Created 4 years, 4 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
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..a8ab80286ae40e28ec81df384d6f62fa03f68d1a
--- /dev/null
+++ b/chrome/installer/setup/setup_singleton.cc
@@ -0,0 +1,89 @@
+// 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 <Windows.h>
+
+#include <algorithm>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+#include "chrome/installer/util/installer_state.h"
+
+namespace installer {
+
+namespace {
+
+base::string16 ReplaceBackslashes(const base::string16& path) {
+ base::string16 path_without_backslashes(path);
+ std::replace(path_without_backslashes.begin(), path_without_backslashes.end(),
+ L'\\', L'/');
+ return path_without_backslashes;
+}
+
+} // namespace
+
+SetupSingleton::SetupSingleton(const InstallerState& installer_state)
grt (UTC plus 2) 2016/08/31 12:03:47 perhaps this should take InstallerState and Instal
fdoray 2016/08/31 19:14:21 Done.
+ : SetupSingleton(installer_state.target_path(),
+ installer_state.system_install()) {}
+
+SetupSingleton::SetupSingleton(const base::FilePath& install_dir,
+ bool system_install) {
+ // Create mutexes and event.
+ const base::string16 name_prefix = system_install ? L"Global\\" : L"Local\\";
grt (UTC plus 2) 2016/08/31 12:03:47 while i'm not sure if/how a user could be logged o
fdoray 2016/08/31 19:14:21 Done.
+ const base::string16 install_dir_without_backslashes(
+ ReplaceBackslashes(install_dir.value()));
+
+ const base::string16 setup_mutex_name =
+ name_prefix + L"ChromeSetupMutex_" + install_dir_without_backslashes;
+ setup_mutex_.Set(::CreateMutex(nullptr, FALSE, setup_mutex_name.c_str()));
grt (UTC plus 2) 2016/08/31 12:03:47 a mutex's name is limited to MAX_PATH chars. to av
fdoray 2016/08/31 19:14:21 Done.
+ DCHECK(setup_mutex_.IsValid());
+
+ const base::string16 exit_event_name =
grt (UTC plus 2) 2016/08/31 12:03:47 is the exit event only used for testing? if so, co
fdoray 2016/08/31 19:14:21 No. The cleanup process will call Wait() between a
+ name_prefix + L"ChromeSetupExitEvent_" + install_dir_without_backslashes;
+ exit_event_.reset(new base::WaitableEvent(base::win::ScopedHandle(
+ ::CreateEvent(nullptr, TRUE, FALSE, exit_event_name.c_str()))));
+
+ // The exit mutex must be acquired before signaling |exit_event_| and released
+ // after acquiring |setup_mutex_|. It ensures that a single SetupSingleton
+ // signals the exit event and waits for |setup_mutex_| to be released at a
+ // time.
+ const base::string16 exit_event_mutex_name = name_prefix +
+ L"ChromeSetupExitEventMutex_" +
+ install_dir_without_backslashes;
+ base::win::ScopedHandle exit_event_mutex(
+ ::CreateMutex(nullptr, FALSE, exit_event_mutex_name.c_str()));
+ DCHECK(exit_event_mutex.IsValid());
+
+ // Ask existing SetupSingletons to release |setup_mutex_| as soon as possible.
+ const DWORD wait_exit_event_mutex_return_value =
+ ::WaitForSingleObject(exit_event_mutex.Get(), INFINITE);
+ DCHECK(wait_exit_event_mutex_return_value == WAIT_ABANDONED ||
+ wait_exit_event_mutex_return_value == WAIT_OBJECT_0);
+ exit_event_->Signal();
+
+ // Acquire |setup_mutex_|.
+ const DWORD wait_setup_mutex_return_value =
+ ::WaitForSingleObject(setup_mutex_.Get(), INFINITE);
fdoray 2016/08/30 20:07:53 This could block forever if a process hangs while
grt (UTC plus 2) 2016/08/31 12:03:47 That's not so good.
fdoray 2016/08/31 19:14:21 setup.exe now returns SETUP_SINGLETON_ACQUISITION_
+ DCHECK(wait_setup_mutex_return_value == WAIT_ABANDONED ||
+ wait_setup_mutex_return_value == WAIT_OBJECT_0);
+ exit_event_->Reset();
+ const BOOL release_mutex_return_value =
+ ::ReleaseMutex(exit_event_mutex.Get());
+ DCHECK(release_mutex_return_value);
+}
+
+SetupSingleton::~SetupSingleton() {
+ ::ReleaseMutex(setup_mutex_.Get());
grt (UTC plus 2) 2016/08/31 12:03:47 how about using base::ScopedGeneric for auto-relea
fdoray 2016/08/31 19:14:21 Having a class that takes care of acquiring + auto
+}
+
+bool SetupSingleton::Wait(const base::TimeDelta& max_time) {
+ const bool exit_event_signaled = exit_event_->TimedWait(max_time);
+ return exit_event_signaled;
+}
+
+} // namespace installer

Powered by Google App Engine
This is Rietveld 408576698