Commit 2b89cb91 authored by oshima@chromium.org's avatar oshima@chromium.org

Chrome OS: Shutdown without blocking when SIGTERM is received.

 Made ShuttingDownWithoutCloseBrowsers a explicit flag.
 Use END_SESSION shutdown type if chrome recieves SIGTERM AND there are tabs that may
 block shutdown.
 Make sure APP_TERMINATING is sent only once.

This fixes SIGABORT crash in two shutdown scenarios:
1) powering off when chrome has beforeunload handler, or
downloads in progress.
2) singout from screen locker when chrome has beforeunload handler or downloads in progress.

 This is simple version of fix to merge to release branch. I'm working on
another CL that will (hopefully) cleanup a bit more.

BUG=chromium-os:20460
TEST=see bug for repro step


Review URL: http://codereview.chromium.org/8262009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106988 0039d316-1c4b-4281-b951-d872f2087c98
parent d7cf069b
......@@ -59,6 +59,9 @@ namespace browser_shutdown {
// Whether the browser is trying to quit (e.g., Quit chosen from menu).
bool g_trying_to_quit = false;
// Whether the browser should quit without closing browsers.
bool g_shutting_down_without_closing_browsers = false;
Time shutdown_started_;
ShutdownType shutdown_type_ = NOT_VALID;
int shutdown_num_processes_;
......@@ -309,11 +312,11 @@ bool IsTryingToQuit() {
}
bool ShuttingDownWithoutClosingBrowsers() {
#if defined(USE_X11)
if (GetShutdownType() == browser_shutdown::END_SESSION)
return true;
#endif
return false;
return g_shutting_down_without_closing_browsers;
}
void SetShuttingDownWithoutClosingBrowsers(bool without_close) {
g_shutting_down_without_closing_browsers = without_close;
}
} // namespace browser_shutdown
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
......@@ -66,11 +66,15 @@ void SetTryingToQuit(bool quitting);
// General accessor.
bool IsTryingToQuit();
// This is true on X during an END_SESSION, when we can no longer depend
// on the X server to be running. As a result we don't explicitly close the
// browser windows, which can lead to conditions which would fail checks.
// This is true on X during an END_SESSION initiated by X IO Error, when we
// can no longer depend on the X server to be running. As a result we don't
// explicitly close the browser windows, which can lead to conditions which
// would fail checks.
bool ShuttingDownWithoutClosingBrowsers();
// Sets the ShuttingDownWithoutClosingBrowsers flag.
void SetShuttingDownWithoutClosingBrowsers(bool without_close);
} // namespace browser_shutdown
#endif // CHROME_BROWSER_BROWSER_SHUTDOWN_H__
......@@ -5,6 +5,7 @@
#include "chrome/browser/chrome_browser_main.h"
#include "base/debug/debugger.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "content/browser/browser_thread.h"
......@@ -55,6 +56,7 @@ int BrowserX11IOErrorHandler(Display* d) {
if (!g_in_x11_io_error_handler) {
g_in_x11_io_error_handler = true;
LOG(ERROR) << "X IO Error detected";
browser_shutdown::SetShuttingDownWithoutClosingBrowsers(true);
BrowserList::SessionEnding();
}
......
......@@ -205,15 +205,28 @@ bool AreAllBrowsersCloseable() {
return true;
}
// Emits APP_TERMINATING notification. It is guaranteed that the
// notification is sent only once.
void NotifyAppTerminating() {
static bool notified = false;
if (notified)
return;
notified = true;
content::NotificationService::current()->Notify(
content::NOTIFICATION_APP_TERMINATING,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
}
#if defined(OS_CHROMEOS)
bool signout = false;
// Whether a session manager requested to shutdown.
bool g_session_manager_requested_shutdown = true;
// Fast shutdown for ChromeOS. It tells session manager to start
// shutdown process when closing browser windows won't be canceled.
// Returns true if fast shutdown is successfully started.
bool FastShutdown() {
signout = true;
if (chromeos::CrosLibrary::Get()->EnsureLoaded()
&& AreAllBrowsersCloseable()) {
BrowserList::NotifyAndTerminate(true);
......@@ -291,16 +304,17 @@ void BrowserList::AttemptExitInternal() {
// static
void BrowserList::NotifyAndTerminate(bool fast_path) {
#if defined(OS_CHROMEOS)
if (!signout)
static bool notified = false;
// Don't ask SessionManager to shutdown if
// a) a shutdown request has already been sent.
// b) shutdown request comes from session manager.
if (notified || g_session_manager_requested_shutdown)
return;
notified = true;
#endif
if (fast_path) {
content::NotificationService::current()->Notify(
content::NOTIFICATION_APP_TERMINATING,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
}
if (fast_path)
NotifyAppTerminating();
#if defined(OS_CHROMEOS)
NotifyWindowManagerAboutSignout();
......@@ -363,10 +377,7 @@ void BrowserList::RemoveBrowser(Browser* browser) {
// to call ProfileManager::ShutdownSessionServices() as part of the
// shutdown, because Browser::WindowClosing() already makes sure that the
// SessionService is created and notified.
content::NotificationService::current()->Notify(
content::NOTIFICATION_APP_TERMINATING,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
NotifyAppTerminating();
AllBrowsersClosedAndAppExiting();
}
}
......@@ -385,11 +396,6 @@ void BrowserList::RemoveObserver(BrowserList::Observer* observer) {
void BrowserList::CloseAllBrowsers() {
bool session_ending =
browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION;
bool force_exit = false;
#if defined(USE_X11)
if (session_ending)
force_exit = true;
#endif
// Tell everyone that we are shutting down.
browser_shutdown::SetTryingToQuit(true);
......@@ -399,10 +405,12 @@ void BrowserList::CloseAllBrowsers() {
// If there are no browsers, send the APP_TERMINATING action here. Otherwise,
// it will be sent by RemoveBrowser() when the last browser has closed.
if (force_exit || browsers_.empty()) {
if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() ||
browsers_.empty()) {
NotifyAndTerminate(true);
return;
}
#if defined(OS_CHROMEOS)
chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
"StartedClosingWindows", false);
......@@ -470,6 +478,7 @@ void BrowserList::AttemptUserExit() {
state->SavePersistentPrefs();
}
}
g_session_manager_requested_shutdown = false;
if (FastShutdown())
return;
#else
......@@ -508,10 +517,18 @@ void BrowserList::AttemptExit() {
}
#if defined(OS_CHROMEOS)
// A function called when SIGTERM is received.
// static
void BrowserList::ExitCleanly() {
// We always mark exit cleanly.
// We always mark exit cleanly because SessionManager may kill
// chrome in 3 seconds after SIGTERM.
g_browser_process->EndSession();
// Don't block when SIGTERM is received. AreaAllBrowsersCloseable()
// can be false in following cases. a) power-off b) signout from
// screen locker.
if (!AreAllBrowsersCloseable())
browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
AttemptExitInternal();
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment