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

Side by Side Diff: chrome/browser/ui/browser_list.cc

Issue 8262009: Chrome OS: Shutdown without blocking when SIGTERM is received. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync Created 9 years, 2 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/chrome_browser_main_x11.cc ('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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/ui/browser_list.h" 5 #include "chrome/browser/ui/browser_list.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "build/build_config.h" 10 #include "build/build_config.h"
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 (*i)->CheckDownloadsInProgress(&normal_downloads_are_present, 194 (*i)->CheckDownloadsInProgress(&normal_downloads_are_present,
195 &incognito_downloads_are_present); 195 &incognito_downloads_are_present);
196 if (normal_downloads_are_present || 196 if (normal_downloads_are_present ||
197 incognito_downloads_are_present || 197 incognito_downloads_are_present ||
198 (*i)->TabsNeedBeforeUnloadFired()) 198 (*i)->TabsNeedBeforeUnloadFired())
199 return false; 199 return false;
200 } 200 }
201 return true; 201 return true;
202 } 202 }
203 203
204 // Emits APP_TERMINATING notification. It is guaranteed that the
205 // notification is sent only once.
206 void NotifyAppTerminating() {
207 static bool notified = false;
208 if (notified)
209 return;
210 notified = true;
211 NotificationService::current()->Notify(content::NOTIFICATION_APP_TERMINATING,
212 NotificationService::AllSources(),
213 NotificationService::NoDetails());
214 }
215
204 #if defined(OS_CHROMEOS) 216 #if defined(OS_CHROMEOS)
205 217
206 bool signout = false;
207
208 // Fast shutdown for ChromeOS. It tells session manager to start 218 // Fast shutdown for ChromeOS. It tells session manager to start
209 // shutdown process when closing browser windows won't be canceled. 219 // shutdown process when closing browser windows won't be canceled.
210 // Returns true if fast shutdown is successfully started. 220 // Returns true if fast shutdown is successfully started.
211 bool FastShutdown() { 221 bool FastShutdown() {
212 signout = true;
213 if (chromeos::CrosLibrary::Get()->EnsureLoaded() 222 if (chromeos::CrosLibrary::Get()->EnsureLoaded()
214 && AreAllBrowsersCloseable()) { 223 && AreAllBrowsersCloseable()) {
215 BrowserList::NotifyAndTerminate(true); 224 BrowserList::NotifyAndTerminate(true);
216 return true; 225 return true;
217 } 226 }
218 return false; 227 return false;
219 } 228 }
220 229
221 void NotifyWindowManagerAboutSignout() { 230 void NotifyWindowManagerAboutSignout() {
222 #if defined(TOOLKIT_USES_GTK) 231 #if defined(TOOLKIT_USES_GTK)
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 // On the Mac, the application continues to run once all windows are closed. 289 // On the Mac, the application continues to run once all windows are closed.
281 // Terminate will result in a CloseAllBrowsers() call, and once (and if) 290 // Terminate will result in a CloseAllBrowsers() call, and once (and if)
282 // that is done, will cause the application to exit cleanly. 291 // that is done, will cause the application to exit cleanly.
283 chrome_browser_application_mac::Terminate(); 292 chrome_browser_application_mac::Terminate();
284 #endif 293 #endif
285 } 294 }
286 295
287 // static 296 // static
288 void BrowserList::NotifyAndTerminate(bool fast_path) { 297 void BrowserList::NotifyAndTerminate(bool fast_path) {
289 #if defined(OS_CHROMEOS) 298 #if defined(OS_CHROMEOS)
290 if (!signout) 299 static bool notified = false;
300 // Do nothing if shutdown request has already been sent.
301 if (notified)
DaveMoore 2011/10/13 16:50:06 Is double protecting this the right thing to do? C
oshima 2011/10/13 17:55:03 The way I understanding is that once we notified W
291 return; 302 return;
303 notified = true;
292 #endif 304 #endif
293 305
294 if (fast_path) { 306 if (fast_path) {
295 NotificationService::current()->Notify( 307 NotifyAppTerminating();
296 content::NOTIFICATION_APP_TERMINATING,
297 NotificationService::AllSources(),
298 NotificationService::NoDetails());
299 } 308 }
300 309
301 #if defined(OS_CHROMEOS) 310 #if defined(OS_CHROMEOS)
302 NotifyWindowManagerAboutSignout(); 311 NotifyWindowManagerAboutSignout();
303 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); 312 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get();
304 if (cros_library->EnsureLoaded()) { 313 if (cros_library->EnsureLoaded()) {
305 // If update has been installed, reboot, otherwise, sign out. 314 // If update has been installed, reboot, otherwise, sign out.
306 if (cros_library->GetUpdateLibrary()->status().status == 315 if (cros_library->GetUpdateLibrary()->status().status ==
307 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { 316 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
308 cros_library->GetUpdateLibrary()->RebootAfterUpdate(); 317 cros_library->GetUpdateLibrary()->RebootAfterUpdate();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 // If we're exiting, send out the APP_TERMINATING notification to allow other 359 // If we're exiting, send out the APP_TERMINATING notification to allow other
351 // modules to shut themselves down. 360 // modules to shut themselves down.
352 if (browsers_.empty() && 361 if (browsers_.empty() &&
353 (browser_shutdown::IsTryingToQuit() || 362 (browser_shutdown::IsTryingToQuit() ||
354 g_browser_process->IsShuttingDown())) { 363 g_browser_process->IsShuttingDown())) {
355 // Last browser has just closed, and this is a user-initiated quit or there 364 // Last browser has just closed, and this is a user-initiated quit or there
356 // is no module keeping the app alive, so send out our notification. No need 365 // is no module keeping the app alive, so send out our notification. No need
357 // to call ProfileManager::ShutdownSessionServices() as part of the 366 // to call ProfileManager::ShutdownSessionServices() as part of the
358 // shutdown, because Browser::WindowClosing() already makes sure that the 367 // shutdown, because Browser::WindowClosing() already makes sure that the
359 // SessionService is created and notified. 368 // SessionService is created and notified.
360 NotificationService::current()->Notify( 369 NotifyAppTerminating();
361 content::NOTIFICATION_APP_TERMINATING,
362 NotificationService::AllSources(),
363 NotificationService::NoDetails());
364 AllBrowsersClosedAndAppExiting(); 370 AllBrowsersClosedAndAppExiting();
365 } 371 }
366 } 372 }
367 373
368 // static 374 // static
369 void BrowserList::AddObserver(BrowserList::Observer* observer) { 375 void BrowserList::AddObserver(BrowserList::Observer* observer) {
370 observers_.AddObserver(observer); 376 observers_.AddObserver(observer);
371 } 377 }
372 378
373 // static 379 // static
374 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { 380 void BrowserList::RemoveObserver(BrowserList::Observer* observer) {
375 observers_.RemoveObserver(observer); 381 observers_.RemoveObserver(observer);
376 } 382 }
377 383
378 // static 384 // static
379 void BrowserList::CloseAllBrowsers() { 385 void BrowserList::CloseAllBrowsers() {
380 bool session_ending = 386 bool session_ending =
381 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; 387 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION;
382 bool force_exit = false;
383 #if defined(USE_X11)
384 if (session_ending)
385 force_exit = true;
386 #endif
387 // Tell everyone that we are shutting down. 388 // Tell everyone that we are shutting down.
388 browser_shutdown::SetTryingToQuit(true); 389 browser_shutdown::SetTryingToQuit(true);
389 390
390 // Before we close the browsers shutdown all session services. That way an 391 // Before we close the browsers shutdown all session services. That way an
391 // exit can restore all browsers open before exiting. 392 // exit can restore all browsers open before exiting.
392 ProfileManager::ShutdownSessionServices(); 393 ProfileManager::ShutdownSessionServices();
393 394
394 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, 395 // If there are no browsers, send the APP_TERMINATING action here. Otherwise,
395 // it will be sent by RemoveBrowser() when the last browser has closed. 396 // it will be sent by RemoveBrowser() when the last browser has closed.
396 if (force_exit || browsers_.empty()) { 397 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() ||
398 browsers_.empty()) {
397 NotifyAndTerminate(true); 399 NotifyAndTerminate(true);
398 return; 400 return;
399 } 401 }
402
400 #if defined(OS_CHROMEOS) 403 #if defined(OS_CHROMEOS)
401 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( 404 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
402 "StartedClosingWindows", false); 405 "StartedClosingWindows", false);
403 #endif 406 #endif
404 for (BrowserList::const_iterator i = BrowserList::begin(); 407 for (BrowserList::const_iterator i = BrowserList::begin();
405 i != BrowserList::end();) { 408 i != BrowserList::end();) {
406 Browser* browser = *i; 409 Browser* browser = *i;
407 browser->window()->Close(); 410 browser->window()->Close();
408 if (!session_ending) { 411 if (!session_ending) {
409 ++i; 412 ++i;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 // If we know that all browsers can be closed without blocking, 498 // If we know that all browsers can be closed without blocking,
496 // don't notify users of crashes beyond this point. 499 // don't notify users of crashes beyond this point.
497 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit 500 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit
498 // so crashes during shutdown are still reported in UMA. 501 // so crashes during shutdown are still reported in UMA.
499 if (AreAllBrowsersCloseable()) 502 if (AreAllBrowsersCloseable())
500 MarkAsCleanShutdown(); 503 MarkAsCleanShutdown();
501 AttemptExitInternal(); 504 AttemptExitInternal();
502 } 505 }
503 506
504 #if defined(OS_CHROMEOS) 507 #if defined(OS_CHROMEOS)
508 // A function called when SIGTERM is received.
505 // static 509 // static
506 void BrowserList::ExitCleanly() { 510 void BrowserList::ExitCleanly() {
507 // We always mark exit cleanly. 511 // We always mark exit cleanly because SessionManager may kill
512 // chrome in 3 seconds after SIGTERM.
508 g_browser_process->EndSession(); 513 g_browser_process->EndSession();
514
515 // Don't block when SIGTERM is received. AreaAllBrowsersCloseable()
516 // can be false in following cases. a) power-off b) signout from
517 // screen locker.
518 if (!AreAllBrowsersCloseable())
519 browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
509 AttemptExitInternal(); 520 AttemptExitInternal();
510 } 521 }
511 #endif 522 #endif
512 523
513 static void TimeLimitedSessionEnding() { 524 static void TimeLimitedSessionEnding() {
514 // Start watching for hang during shutdown, and crash it if takes too long. 525 // Start watching for hang during shutdown, and crash it if takes too long.
515 // We disarm when |shutdown_watcher| object is destroyed, which is when we 526 // We disarm when |shutdown_watcher| object is destroyed, which is when we
516 // exit this function. 527 // exit this function.
517 ShutdownWatcherHelper shutdown_watcher; 528 ShutdownWatcherHelper shutdown_watcher;
518 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90)); 529 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90));
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 // If no more TabContents from Browsers, check the BackgroundPrintingManager. 798 // If no more TabContents from Browsers, check the BackgroundPrintingManager.
788 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { 799 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) {
789 cur_ = *bg_printing_iterator_; 800 cur_ = *bg_printing_iterator_;
790 CHECK(cur_); 801 CHECK(cur_);
791 ++bg_printing_iterator_; 802 ++bg_printing_iterator_;
792 return; 803 return;
793 } 804 }
794 // Reached the end - no more TabContents. 805 // Reached the end - no more TabContents.
795 cur_ = NULL; 806 cur_ = NULL;
796 } 807 }
OLDNEW
« no previous file with comments | « chrome/browser/chrome_browser_main_x11.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698