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

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

Issue 349263004: Fix Windows logoff race. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rejig the rundown post accounting for better encapsulation. Created 6 years, 6 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 | « no previous file | chrome/browser/lifetime/application_lifetime.cc » ('j') | 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/browser_process_impl.h" 5 #include "chrome/browser/browser_process_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 #if defined(OS_MACOSX) 372 #if defined(OS_MACOSX)
373 base::MessageLoop::current()->PostTask( 373 base::MessageLoop::current()->PostTask(
374 FROM_HERE, 374 FROM_HERE,
375 base::Bind(ChromeBrowserMainPartsMac::DidEndMainMessageLoop)); 375 base::Bind(ChromeBrowserMainPartsMac::DidEndMainMessageLoop));
376 #endif 376 #endif
377 base::MessageLoop::current()->Quit(); 377 base::MessageLoop::current()->Quit();
378 } 378 }
379 return module_ref_count_; 379 return module_ref_count_;
380 } 380 }
381 381
382 namespace {
383
384 class RundownTaskCounter :
385 public base::RefCountedThreadSafe<RundownTaskCounter> {
386 public:
387 // Creates a rundown task counter with |count|.
388 explicit RundownTaskCounter(size_t count);
389
390 // Posts a rundown task to |task_runner|.
391 void Post(base::SequencedTaskRunner* task_runner);
392
393 // Decrements the counter and releases the wait on zero.
394 void Decrement();
erikwright (departed) 2014/06/24 16:10:53 Make this private.
Sigurður Ásgeirsson 2014/06/24 17:17:26 Done.
395
396 // Waits until the count is zero or |max_time| has passed.
397 bool TimedWait(const base::TimeDelta& max_time);
398
399 private:
400 friend class base::RefCountedThreadSafe<RundownTaskCounter>;
401 ~RundownTaskCounter() {}
402
403 // Keeps track of how many posts are remaining.
404 size_t posts_remaining_;
405
406 base::AtomicRefCount count_;
407 base::WaitableEvent waitable_event_;
408
409 DISALLOW_COPY_AND_ASSIGN(RundownTaskCounter);
410 };
411
412 RundownTaskCounter::RundownTaskCounter(size_t count)
413 : posts_remaining_(count), count_(count), waitable_event_(true, false) {
414 DCHECK_GE(count, 1U);
415 }
416
417 void RundownTaskCounter::Post(base::SequencedTaskRunner* task_runner) {
418 DCHECK_GT(posts_remaining_, 0U);
419
420 --posts_remaining_;
421 task_runner->PostTask(FROM_HERE,
422 base::Bind(&RundownTaskCounter::Decrement, this));
423 }
424
425 void RundownTaskCounter::Decrement() {
426 if (!base::AtomicRefCountDec(&count_)) {
427 waitable_event_.Signal();
428 }
429 }
430
431 bool RundownTaskCounter::TimedWait(const base::TimeDelta& max_time) {
432 // If this check fires, the counter was initialized with the wrong count.
433 DCHECK_EQ(posts_remaining_, 0U);
434 return waitable_event_.TimedWait(max_time);
435 }
436
437 } // namespace
438
382 void BrowserProcessImpl::EndSession() { 439 void BrowserProcessImpl::EndSession() {
383 // Mark all the profiles as clean. 440 // Mark all the profiles as clean.
384 ProfileManager* pm = profile_manager(); 441 ProfileManager* pm = profile_manager();
385 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); 442 std::vector<Profile*> profiles(pm->GetLoadedProfiles());
386 for (size_t i = 0; i < profiles.size(); ++i) 443
387 profiles[i]->SetExitType(Profile::EXIT_SESSION_ENDED); 444 // We create the rundown task counter with a count for each profile.
445 size_t rundown_count = profiles.size();
446 #if !defined(OS_CHROMEOS)
447 // Add one for local state on Windows.
erikwright (departed) 2014/06/24 16:10:53 This comment is inaccurate - it's on non-ChromeOS
Sigurður Ásgeirsson 2014/06/24 17:17:26 Removed.
448 rundown_count += 1;
449 #endif
450 scoped_refptr<RundownTaskCounter> rundown_counter(
451 new RundownTaskCounter(rundown_count));
452
453 for (size_t i = 0; i < profiles.size(); ++i) {
454 Profile* profile = profiles[i];
455 profile->SetExitType(Profile::EXIT_SESSION_ENDED);
456
457 rundown_counter->Post(profile->GetIOTaskRunner());
458 }
388 459
389 // Tell the metrics service it was cleanly shutdown. 460 // Tell the metrics service it was cleanly shutdown.
390 MetricsService* metrics = g_browser_process->metrics_service(); 461 MetricsService* metrics = g_browser_process->metrics_service();
391 if (metrics && local_state()) { 462 if (metrics && local_state()) {
392 metrics->RecordStartOfSessionEnd(); 463 metrics->RecordStartOfSessionEnd();
393 #if !defined(OS_CHROMEOS) 464 #if !defined(OS_CHROMEOS)
394 // MetricsService lazily writes to prefs, force it to write now. 465 // MetricsService lazily writes to prefs, force it to write now.
395 // On ChromeOS, chrome gets killed when hangs, so no need to 466 // On ChromeOS, chrome gets killed when hangs, so no need to
396 // commit metrics::prefs::kStabilitySessionEndCompleted change immediately. 467 // commit metrics::prefs::kStabilitySessionEndCompleted change immediately.
397 local_state()->CommitPendingWrite(); 468 local_state()->CommitPendingWrite();
469
470 rundown_counter->Post(local_state_task_runner_);
398 #endif 471 #endif
399 } 472 }
400 473
401 // http://crbug.com/125207 474 // http://crbug.com/125207
402 base::ThreadRestrictions::ScopedAllowWait allow_wait; 475 base::ThreadRestrictions::ScopedAllowWait allow_wait;
403 476
404 // We must write that the profile and metrics service shutdown cleanly, 477 // We must write that the profile and metrics service shutdown cleanly,
405 // otherwise on startup we'll think we crashed. So we block until done and 478 // otherwise on startup we'll think we crashed. So we block until done and
406 // then proceed with normal shutdown. 479 // then proceed with normal shutdown.
407 #if defined(USE_X11) || defined(OS_WIN) 480 #if defined(USE_X11) || defined(OS_WIN)
408 // Create a waitable event to block on file writing being complete. 481 // Do a best-effort wait on the successful countdown of rundown tasks. Note
482 // that if we don't complete "quickly enough", Windows will terminate our
483 // process.
409 // 484 //
410 // On Windows, we previously posted a message to FILE and then ran a nested 485 // On Windows, we previously posted a message to FILE and then ran a nested
411 // message loop, waiting for that message to be processed until quitting. 486 // message loop, waiting for that message to be processed until quitting.
412 // However, doing so means that other messages will also be processed. In 487 // However, doing so means that other messages will also be processed. In
413 // particular, if the GPU process host notices that the GPU has been killed 488 // particular, if the GPU process host notices that the GPU has been killed
414 // during shutdown, it races exiting the nested loop with the process host 489 // during shutdown, it races exiting the nested loop with the process host
415 // blocking the message loop attempting to re-establish a connection to the 490 // blocking the message loop attempting to re-establish a connection to the
416 // GPU process synchronously. Because the system may not be allowing 491 // GPU process synchronously. Because the system may not be allowing
417 // processes to launch, this can result in a hang. See 492 // processes to launch, this can result in a hang. See
418 // http://crbug.com/318527. 493 // http://crbug.com/318527.
419 scoped_ptr<base::WaitableEvent> done_writing( 494 rundown_counter->TimedWait(
420 new base::WaitableEvent(false, false)); 495 base::TimeDelta::FromSeconds(kEndSessionTimeoutSeconds));
421 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
422 base::Bind(Signal, done_writing.get()));
423 // If all file writes haven't cleared in the timeout, leak the WaitableEvent
424 // so that there's no race to reference it in Signal().
425 if (!done_writing->TimedWait(
426 base::TimeDelta::FromSeconds(kEndSessionTimeoutSeconds))) {
427 ignore_result(done_writing.release());
428 }
429 #else 496 #else
430 NOTIMPLEMENTED(); 497 NOTIMPLEMENTED();
431 #endif 498 #endif
432 } 499 }
433 500
434 MetricsServicesManager* BrowserProcessImpl::GetMetricsServicesManager() { 501 MetricsServicesManager* BrowserProcessImpl::GetMetricsServicesManager() {
435 DCHECK(CalledOnValidThread()); 502 DCHECK(CalledOnValidThread());
436 if (!metrics_services_manager_) 503 if (!metrics_services_manager_)
437 metrics_services_manager_.reset(new MetricsServicesManager(local_state())); 504 metrics_services_manager_.reset(new MetricsServicesManager(local_state()));
438 return metrics_services_manager_.get(); 505 return metrics_services_manager_.get();
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after
1101 } 1168 }
1102 1169
1103 void BrowserProcessImpl::OnAutoupdateTimer() { 1170 void BrowserProcessImpl::OnAutoupdateTimer() {
1104 if (CanAutorestartForUpdate()) { 1171 if (CanAutorestartForUpdate()) {
1105 DLOG(WARNING) << "Detected update. Restarting browser."; 1172 DLOG(WARNING) << "Detected update. Restarting browser.";
1106 RestartBackgroundInstance(); 1173 RestartBackgroundInstance();
1107 } 1174 }
1108 } 1175 }
1109 1176
1110 #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) 1177 #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/lifetime/application_lifetime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698