Chromium Code Reviews| Index: chrome/browser/process_singleton_win.cc |
| =================================================================== |
| --- chrome/browser/process_singleton_win.cc (revision 40535) |
| +++ chrome/browser/process_singleton_win.cc (working copy) |
| @@ -10,6 +10,7 @@ |
| #include "base/command_line.h" |
| #include "base/path_service.h" |
| #include "base/process_util.h" |
| +#include "base/scoped_handle.h" |
| #include "base/win_util.h" |
| #include "chrome/browser/browser_init.h" |
| #include "chrome/browser/browser_process.h" |
| @@ -18,6 +19,7 @@ |
| #include "chrome/common/chrome_constants.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/result_codes.h" |
| +#include "chrome/installer/util/browser_distribution.h" |
| #include "grit/chromium_strings.h" |
| #include "grit/generated_resources.h" |
| @@ -37,12 +39,38 @@ |
| // Look for a Chrome instance that uses the same profile directory. |
| ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir) |
| : window_(NULL), locked_(false), foreground_window_(NULL) { |
| - // FindWindoEx and Create() should be one atomic operation in order to not |
| - // have a race condition. |
| - remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, chrome::kMessageWindowClass, |
| - user_data_dir.ToWStringHack().c_str()); |
| - if (!remote_window_) |
| - Create(); |
| + std::wstring user_data_dir_str(user_data_dir.ToWStringHack()); |
| + remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, |
| + chrome::kMessageWindowClass, |
| + user_data_dir_str.c_str()); |
| + if (!remote_window_) { |
| + // Make sure we will be the one and only process creating the window. |
| + // We use a named Mutex since we are protecting against multi-process |
| + // access. As documented, it's clearer to NOT request ownership on creation |
| + // since it isn't guaranteed we will get it. It is better to create it |
| + // without ownership and explicitly get the ownership afterward. |
| + std::wstring mutex_name(L"Local\\ProcessSingletonStartup!"); |
| + mutex_name += BrowserDistribution::GetDistribution()->GetAppGuid(); |
| + ScopedHandle only_me(CreateMutex(NULL, FALSE, mutex_name.c_str())); |
| + DCHECK(only_me.Get() != NULL) << "GetLastError = " << GetLastError(); |
| + |
| + // This is how we acquire the mutex (as opposed to the initial ownership). |
| + DWORD result = WaitForSingleObject(only_me, INFINITE); |
|
Sigurður Ásgeirsson
2012/04/11 12:17:40
WFSO can also return WAIT_ABANDONED for success. T
|
| + DCHECK(result == WAIT_OBJECT_0) << "Result = " << result << |
| + "GetLastError = " << GetLastError(); |
| + |
| + // We now own the mutex so we are the only process that can create the |
| + // window at this time, but we must still check if someone created it |
| + // between the time where we looked for it above and the time the mutex |
| + // was given to us. |
| + remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, |
| + chrome::kMessageWindowClass, |
| + user_data_dir_str.c_str()); |
| + if (!remote_window_) |
| + Create(); |
| + BOOL success = ReleaseMutex(only_me); |
| + DCHECK(success) << "GetLastError = " << GetLastError(); |
| + } |
| } |
| ProcessSingleton::~ProcessSingleton() { |