| OLD | NEW |
| 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 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 waitable_event_.Signal(); | 439 waitable_event_.Signal(); |
| 440 } | 440 } |
| 441 | 441 |
| 442 bool RundownTaskCounter::TimedWait(const base::TimeDelta& max_time) { | 442 bool RundownTaskCounter::TimedWait(const base::TimeDelta& max_time) { |
| 443 // Decrement the excess count from the constructor. | 443 // Decrement the excess count from the constructor. |
| 444 Decrement(); | 444 Decrement(); |
| 445 | 445 |
| 446 return waitable_event_.TimedWait(max_time); | 446 return waitable_event_.TimedWait(max_time); |
| 447 } | 447 } |
| 448 | 448 |
| 449 bool ExperimentUseBrokenSynchronization() { | |
| 450 // The logoff behavior used to have a race, whereby it would perform profile | |
| 451 // IO writes on the blocking thread pool, but would sycnhronize to the FILE | |
| 452 // thread. Windows feels free to terminate any process that's hidden or | |
| 453 // destroyed all it's windows, and sometimes Chrome would be terminated | |
| 454 // with pending profile IO due to this mis-synchronization. | |
| 455 // Under the "WindowsLogoffRace" experiment group, the broken behavior is | |
| 456 // emulated, in order to allow measuring what fraction of unclean shutdowns | |
| 457 // are due to this bug. | |
| 458 const std::string group_name = | |
| 459 base::FieldTrialList::FindFullName("WindowsLogoffRace"); | |
| 460 return group_name == "BrokenSynchronization"; | |
| 461 } | |
| 462 | |
| 463 } // namespace | 449 } // namespace |
| 464 | 450 |
| 465 void BrowserProcessImpl::EndSession() { | 451 void BrowserProcessImpl::EndSession() { |
| 466 bool use_broken_synchronization = ExperimentUseBrokenSynchronization(); | |
| 467 | |
| 468 // Mark all the profiles as clean. | 452 // Mark all the profiles as clean. |
| 469 ProfileManager* pm = profile_manager(); | 453 ProfileManager* pm = profile_manager(); |
| 470 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); | 454 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); |
| 471 scoped_refptr<RundownTaskCounter> rundown_counter(new RundownTaskCounter()); | 455 scoped_refptr<RundownTaskCounter> rundown_counter(new RundownTaskCounter()); |
| 472 for (size_t i = 0; i < profiles.size(); ++i) { | 456 for (size_t i = 0; i < profiles.size(); ++i) { |
| 473 Profile* profile = profiles[i]; | 457 Profile* profile = profiles[i]; |
| 474 profile->SetExitType(Profile::EXIT_SESSION_ENDED); | 458 profile->SetExitType(Profile::EXIT_SESSION_ENDED); |
| 475 | 459 |
| 476 if (!use_broken_synchronization) | 460 rundown_counter->Post(profile->GetIOTaskRunner().get()); |
| 477 rundown_counter->Post(profile->GetIOTaskRunner().get()); | |
| 478 } | 461 } |
| 479 | 462 |
| 480 // Tell the metrics service it was cleanly shutdown. | 463 // Tell the metrics service it was cleanly shutdown. |
| 481 metrics::MetricsService* metrics = g_browser_process->metrics_service(); | 464 metrics::MetricsService* metrics = g_browser_process->metrics_service(); |
| 482 if (metrics && local_state()) { | 465 if (metrics && local_state()) { |
| 483 metrics->RecordStartOfSessionEnd(); | 466 metrics->RecordStartOfSessionEnd(); |
| 484 #if !defined(OS_CHROMEOS) | 467 #if !defined(OS_CHROMEOS) |
| 485 // MetricsService lazily writes to prefs, force it to write now. | 468 // MetricsService lazily writes to prefs, force it to write now. |
| 486 // On ChromeOS, chrome gets killed when hangs, so no need to | 469 // On ChromeOS, chrome gets killed when hangs, so no need to |
| 487 // commit metrics::prefs::kStabilitySessionEndCompleted change immediately. | 470 // commit metrics::prefs::kStabilitySessionEndCompleted change immediately. |
| 488 local_state()->CommitPendingWrite(); | 471 local_state()->CommitPendingWrite(); |
| 489 | 472 |
| 490 if (!use_broken_synchronization) | 473 rundown_counter->Post(local_state_task_runner_.get()); |
| 491 rundown_counter->Post(local_state_task_runner_.get()); | |
| 492 #endif | 474 #endif |
| 493 } | 475 } |
| 494 | 476 |
| 495 // http://crbug.com/125207 | 477 // http://crbug.com/125207 |
| 496 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 478 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
| 497 | 479 |
| 498 // We must write that the profile and metrics service shutdown cleanly, | 480 // We must write that the profile and metrics service shutdown cleanly, |
| 499 // otherwise on startup we'll think we crashed. So we block until done and | 481 // otherwise on startup we'll think we crashed. So we block until done and |
| 500 // then proceed with normal shutdown. | 482 // then proceed with normal shutdown. |
| 501 // | 483 // |
| 502 // If you change the condition here, be sure to also change | 484 // If you change the condition here, be sure to also change |
| 503 // ProfileBrowserTests to match. | 485 // ProfileBrowserTests to match. |
| 504 #if defined(USE_X11) || defined(OS_WIN) | 486 #if defined(USE_X11) || defined(OS_WIN) |
| 505 if (use_broken_synchronization) { | |
| 506 rundown_counter->Post( | |
| 507 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get()); | |
| 508 } | |
| 509 | |
| 510 // Do a best-effort wait on the successful countdown of rundown tasks. Note | 487 // Do a best-effort wait on the successful countdown of rundown tasks. Note |
| 511 // that if we don't complete "quickly enough", Windows will terminate our | 488 // that if we don't complete "quickly enough", Windows will terminate our |
| 512 // process. | 489 // process. |
| 513 // | 490 // |
| 514 // On Windows, we previously posted a message to FILE and then ran a nested | 491 // On Windows, we previously posted a message to FILE and then ran a nested |
| 515 // message loop, waiting for that message to be processed until quitting. | 492 // message loop, waiting for that message to be processed until quitting. |
| 516 // However, doing so means that other messages will also be processed. In | 493 // However, doing so means that other messages will also be processed. In |
| 517 // particular, if the GPU process host notices that the GPU has been killed | 494 // particular, if the GPU process host notices that the GPU has been killed |
| 518 // during shutdown, it races exiting the nested loop with the process host | 495 // during shutdown, it races exiting the nested loop with the process host |
| 519 // blocking the message loop attempting to re-establish a connection to the | 496 // blocking the message loop attempting to re-establish a connection to the |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1220 } | 1197 } |
| 1221 | 1198 |
| 1222 void BrowserProcessImpl::OnAutoupdateTimer() { | 1199 void BrowserProcessImpl::OnAutoupdateTimer() { |
| 1223 if (CanAutorestartForUpdate()) { | 1200 if (CanAutorestartForUpdate()) { |
| 1224 DLOG(WARNING) << "Detected update. Restarting browser."; | 1201 DLOG(WARNING) << "Detected update. Restarting browser."; |
| 1225 RestartBackgroundInstance(); | 1202 RestartBackgroundInstance(); |
| 1226 } | 1203 } |
| 1227 } | 1204 } |
| 1228 | 1205 |
| 1229 #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) | 1206 #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) |
| OLD | NEW |