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

Side by Side Diff: chrome/browser/process_singleton_win.cc

Issue 10702159: Implement lock file for windows profiles. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moved the check to after checking for local instances. Created 8 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/process_singleton.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/process_singleton.h" 5 #include "chrome/browser/process_singleton.h"
6 6
7 #include "base/base_paths.h" 7 #include "base/base_paths.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/file_path.h" 9 #include "base/file_path.h"
10 #include "base/path_service.h" 10 #include "base/path_service.h"
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 return true; 141 return true;
142 } 142 }
143 return false; 143 return false;
144 } 144 }
145 145
146 // Look for a Chrome instance that uses the same profile directory. 146 // Look for a Chrome instance that uses the same profile directory.
147 // If there isn't one, create a message window with its title set to 147 // If there isn't one, create a message window with its title set to
148 // the profile directory path. 148 // the profile directory path.
149 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir) 149 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir)
150 : window_(NULL), locked_(false), foreground_window_(NULL), 150 : window_(NULL), locked_(false), foreground_window_(NULL),
151 is_virtualized_(false) { 151 is_virtualized_(false), lock_file_(INVALID_HANDLE_VALUE) {
152 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, 152 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL,
153 chrome::kMessageWindowClass, 153 chrome::kMessageWindowClass,
154 user_data_dir.value().c_str()); 154 user_data_dir.value().c_str());
155 if (!remote_window_ && !EscapeVirtualization(user_data_dir)) { 155 if (!remote_window_ && !EscapeVirtualization(user_data_dir)) {
156 // Make sure we will be the one and only process creating the window. 156 // Make sure we will be the one and only process creating the window.
157 // We use a named Mutex since we are protecting against multi-process 157 // We use a named Mutex since we are protecting against multi-process
158 // access. As documented, it's clearer to NOT request ownership on creation 158 // access. As documented, it's clearer to NOT request ownership on creation
159 // since it isn't guaranteed we will get it. It is better to create it 159 // since it isn't guaranteed we will get it. It is better to create it
160 // without ownership and explicitly get the ownership afterward. 160 // without ownership and explicitly get the ownership afterward.
161 std::wstring mutex_name(L"Local\\ChromeProcessSingletonStartup!"); 161 std::wstring mutex_name(L"Local\\ChromeProcessSingletonStartup!");
162 base::win::ScopedHandle only_me( 162 base::win::ScopedHandle only_me(
163 CreateMutex(NULL, FALSE, mutex_name.c_str())); 163 CreateMutex(NULL, FALSE, mutex_name.c_str()));
164 DCHECK(only_me.Get() != NULL) << "GetLastError = " << GetLastError(); 164 DCHECK(only_me.Get() != NULL) << "GetLastError = " << GetLastError();
165 165
166 // This is how we acquire the mutex (as opposed to the initial ownership). 166 // This is how we acquire the mutex (as opposed to the initial ownership).
167 DWORD result = WaitForSingleObject(only_me, INFINITE); 167 DWORD result = WaitForSingleObject(only_me, INFINITE);
168 DCHECK(result == WAIT_OBJECT_0) << "Result = " << result << 168 DCHECK(result == WAIT_OBJECT_0) << "Result = " << result <<
169 "GetLastError = " << GetLastError(); 169 "GetLastError = " << GetLastError();
170 170
171 // We now own the mutex so we are the only process that can create the 171 // We now own the mutex so we are the only process that can create the
172 // window at this time, but we must still check if someone created it 172 // window at this time, but we must still check if someone created it
173 // between the time where we looked for it above and the time the mutex 173 // between the time where we looked for it above and the time the mutex
174 // was given to us. 174 // was given to us.
175 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, 175 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL,
176 chrome::kMessageWindowClass, 176 chrome::kMessageWindowClass,
177 user_data_dir.value().c_str()); 177 user_data_dir.value().c_str());
178 if (!remote_window_) { 178 // We have to make sure there is no Chrome instance running on another
cpu_(ooo_6.6-7.5) 2012/07/13 23:16:53 why do it if the directory is not remote?
pastarmovj 2012/07/14 01:21:58 To check if a path contains a reparse point hence
179 // machine that uses the same profile.
180 FilePath lock_file_path = user_data_dir.AppendASCII("lockfile");
181 lock_file_ = CreateFile(lock_file_path.value().c_str(),
182 GENERIC_WRITE,
183 FILE_SHARE_READ,
184 NULL,
185 CREATE_NEW,
186 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
187 NULL);
188 DWORD error = GetLastError();
189 LOG(ERROR) << "@@@ First lock file attempt : " << lock_file_
190 << " code " << error;
191 if (lock_file_ == INVALID_HANDLE_VALUE && error == ERROR_FILE_EXISTS) {
192 // If we are inside here that means that some other machine has or had an
193 // active chrome process. This second try destinguishes between stale file
194 // and really actively opened file. We should directly do this check but
195 // for completeness we do both check sequentially.
196 lock_file_ = CreateFile(lock_file_path.value().c_str(),
197 GENERIC_WRITE,
198 FILE_SHARE_READ,
199 NULL,
200 OPEN_EXISTING,
201 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
202 NULL);
203 error = GetLastError();
204 LOG(ERROR) << "@@@ Second lock file attempt : " << lock_file_
205 << " code " << error;
206 }
207 if (lock_file_ == INVALID_HANDLE_VALUE) {
208 // If both attempts failed we are left with no other option but to admit
209 // defeat and make harakiri to ourselves.
210 LOG(ERROR) << "@@@ There is another chrome process that is still active";
211 }
212
213 if (!remote_window_ && lock_file_ != INVALID_HANDLE_VALUE) {
179 HINSTANCE hinst = base::GetModuleFromAddress(&ThunkWndProc); 214 HINSTANCE hinst = base::GetModuleFromAddress(&ThunkWndProc);
180 215
181 WNDCLASSEX wc = {0}; 216 WNDCLASSEX wc = {0};
182 wc.cbSize = sizeof(wc); 217 wc.cbSize = sizeof(wc);
183 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>; 218 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>;
184 wc.hInstance = hinst; 219 wc.hInstance = hinst;
185 wc.lpszClassName = chrome::kMessageWindowClass; 220 wc.lpszClassName = chrome::kMessageWindowClass;
186 ATOM clazz = ::RegisterClassEx(&wc); 221 ATOM clazz = ::RegisterClassEx(&wc);
187 DCHECK(clazz); 222 DCHECK(clazz);
188 223
(...skipping 11 matching lines...) Expand all
200 235
201 ProcessSingleton::~ProcessSingleton() { 236 ProcessSingleton::~ProcessSingleton() {
202 // We need to unregister the window as late as possible so that we can detect 237 // We need to unregister the window as late as possible so that we can detect
203 // another instance of chrome running. Otherwise we may end up writing out 238 // another instance of chrome running. Otherwise we may end up writing out
204 // data while a new chrome is starting up. 239 // data while a new chrome is starting up.
205 if (window_) { 240 if (window_) {
206 ::DestroyWindow(window_); 241 ::DestroyWindow(window_);
207 ::UnregisterClass(chrome::kMessageWindowClass, 242 ::UnregisterClass(chrome::kMessageWindowClass,
208 base::GetModuleFromAddress(&ThunkWndProc)); 243 base::GetModuleFromAddress(&ThunkWndProc));
209 } 244 }
245 if (lock_file_ != INVALID_HANDLE_VALUE)
246 CloseHandle(lock_file_);
cpu_(ooo_6.6-7.5) 2012/07/13 23:16:53 why close it here?
pastarmovj 2012/07/14 01:21:58 Mmmm...clean up...I guess :-) . Well basically th
210 } 247 }
211 248
212 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { 249 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() {
213 if (is_virtualized_) 250 if (is_virtualized_)
214 return PROCESS_NOTIFIED; // We already spawned the process in this case. 251 return PROCESS_NOTIFIED; // We already spawned the process in this case.
215 else if (!remote_window_) 252 else if (!remote_window_)
216 return PROCESS_NONE; 253 return PROCESS_NONE;
217 254
218 // Found another window, send our command line to it 255 // Found another window, send our command line to it
219 // format is "START\0<<<current directory>>>\0<<<commandline>>>". 256 // format is "START\0<<<current directory>>>\0<<<commandline>>>".
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 return result; 329 return result;
293 return Create(notification_callback) ? PROCESS_NONE : PROFILE_IN_USE; 330 return Create(notification_callback) ? PROCESS_NONE : PROFILE_IN_USE;
294 } 331 }
295 332
296 // On Windows, there is no need to call Create() since the message 333 // On Windows, there is no need to call Create() since the message
297 // window is created in the constructor but to avoid having more 334 // window is created in the constructor but to avoid having more
298 // platform specific code in browser_main.cc we tolerate calls to 335 // platform specific code in browser_main.cc we tolerate calls to
299 // Create(). 336 // Create().
300 bool ProcessSingleton::Create( 337 bool ProcessSingleton::Create(
301 const NotificationCallback& notification_callback) { 338 const NotificationCallback& notification_callback) {
339 if (lock_file_ == INVALID_HANDLE_VALUE)
340 return false;
341
cpu_(ooo_6.6-7.5) 2012/07/13 23:16:53 and not sure we need this here either..
pastarmovj 2012/07/14 01:21:58 This actually will make the newly started process
302 DCHECK(!remote_window_); 342 DCHECK(!remote_window_);
303 DCHECK(notification_callback_.is_null()); 343 DCHECK(notification_callback_.is_null());
304 344
305 if (window_ != NULL) 345 if (window_ != NULL)
306 notification_callback_ = notification_callback; 346 notification_callback_ = notification_callback;
307 347
308 return window_ != NULL; 348 return window_ != NULL;
309 } 349 }
310 350
311 void ProcessSingleton::Cleanup() { 351 void ProcessSingleton::Cleanup() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 switch (message) { 387 switch (message) {
348 case WM_COPYDATA: 388 case WM_COPYDATA:
349 return OnCopyData(reinterpret_cast<HWND>(wparam), 389 return OnCopyData(reinterpret_cast<HWND>(wparam),
350 reinterpret_cast<COPYDATASTRUCT*>(lparam)); 390 reinterpret_cast<COPYDATASTRUCT*>(lparam));
351 default: 391 default:
352 break; 392 break;
353 } 393 }
354 394
355 return ::DefWindowProc(hwnd, message, wparam, lparam); 395 return ::DefWindowProc(hwnd, message, wparam, lparam);
356 } 396 }
OLDNEW
« no previous file with comments | « chrome/browser/process_singleton.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698