Chromium Code Reviews| 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 |