зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1825917 - Have a ShutdownReason annotation and identify OS shutdown on Windows. r=xpcom-reviewers,gstoll,nika
Differential Revision: https://phabricator.services.mozilla.com/D174899
This commit is contained in:
Родитель
79e171fd9f
Коммит
ca12388a58
|
@ -401,7 +401,13 @@ nsAppStartup::Quit(uint32_t aMode, int aExitCode, bool* aUserAllowedQuit) {
|
|||
auto shutdownMode = ((aMode & eRestart) != 0)
|
||||
? mozilla::AppShutdownMode::Restart
|
||||
: mozilla::AppShutdownMode::Normal;
|
||||
mozilla::AppShutdown::Init(shutdownMode, aExitCode);
|
||||
// TODO: Add (or pass in) more reasons here for Mac and Linux, see
|
||||
// bug 1827643 and bug 1827644.
|
||||
// See as example the Windows WM_ENDSESSION handling.
|
||||
auto shutdownReason = ((aMode & eRestart) != 0)
|
||||
? mozilla::AppShutdownReason::AppRestart
|
||||
: mozilla::AppShutdownReason::AppClose;
|
||||
mozilla::AppShutdown::Init(shutdownMode, aExitCode, shutdownReason);
|
||||
|
||||
if (mozilla::AppShutdown::IsRestarting()) {
|
||||
// Mark the next startup as a restart.
|
||||
|
|
|
@ -824,6 +824,13 @@ ShutdownProgress:
|
|||
type: string
|
||||
ping: true
|
||||
|
||||
ShutdownReason:
|
||||
description: >
|
||||
One out of "Unknown", "AppClose", "AppRestart", "OSForceClose",
|
||||
"OSSessionEnd", "OSShutdown" or "WinUnexpectedMozQuit".
|
||||
type: string
|
||||
ping: true
|
||||
|
||||
StartupCrash:
|
||||
description: >
|
||||
If set to 1 then this crash occurred during startup.
|
||||
|
|
|
@ -5141,6 +5141,7 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
static const bool sSwitchKeyboardLayout =
|
||||
Preferences::GetBool("intl.keyboard.per_window_layout", false);
|
||||
static Maybe<bool> sCanQuit;
|
||||
AppShutdownReason shutdownReason = AppShutdownReason::Unknown;
|
||||
|
||||
// (Large blocks of code should be broken out into OnEvent handlers.)
|
||||
switch (msg) {
|
||||
|
@ -5177,45 +5178,77 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
#endif
|
||||
break;
|
||||
|
||||
case WM_ENDSESSION:
|
||||
case MOZ_WM_APP_QUIT:
|
||||
// For WM_ENDSESSION, wParam indicates whether the session is being ended
|
||||
// (TRUE) or not (FALSE)
|
||||
if (msg == MOZ_WM_APP_QUIT || (wParam && sCanQuit.valueOr(false))) {
|
||||
// Let's fake a shutdown sequence without actually closing windows etc.
|
||||
// to avoid Windows killing us in the middle. A proper shutdown would
|
||||
// require having a chance to pump some messages. Unfortunately
|
||||
// Windows won't let us do that. Bug 212316.
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
mozilla::services::GetObserverService();
|
||||
const char16_t* syncShutdown = u"syncShutdown";
|
||||
const char16_t* quitType = GetQuitType();
|
||||
|
||||
AppShutdown::Init(AppShutdownMode::Normal, 0);
|
||||
|
||||
obsServ->NotifyObservers(nullptr, "quit-application-granted",
|
||||
syncShutdown);
|
||||
obsServ->NotifyObservers(nullptr, "quit-application-forced", nullptr);
|
||||
|
||||
AppShutdown::OnShutdownConfirmed();
|
||||
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownConfirmed,
|
||||
quitType);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown,
|
||||
nullptr);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown,
|
||||
nullptr);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown, nullptr);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM,
|
||||
nullptr);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry,
|
||||
nullptr);
|
||||
|
||||
AppShutdown::DoImmediateExit();
|
||||
case WM_ENDSESSION: {
|
||||
// For WM_ENDSESSION, wParam indicates whether we need to shutdown
|
||||
// (TRUE) or not (FALSE).
|
||||
//
|
||||
// TODO: It is not clear if checking sCanQuit here is the right thing
|
||||
// to do. From the WM_ENDSESSION documentation it seems there are cases
|
||||
// where we just need to quit, always. Windows might even have ignored
|
||||
// the WM_QUERYENDSESSION result or sCanQuit might be unset if we did
|
||||
// not pass through WM_QUERYENDSESSION at all ?
|
||||
if (!(wParam && sCanQuit.valueOr(false))) {
|
||||
sCanQuit.reset();
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
sCanQuit.reset();
|
||||
result = true;
|
||||
// According to WM_ENDSESSION lParam documentation:
|
||||
// 0 -> OS shutdown or restart (no way to distinguish)
|
||||
// ENDSESSION_LOGOFF -> User is logging off
|
||||
// ENDSESSION_CLOSEAPP -> Application must shutdown
|
||||
// ENDSESSION_CRITICAL -> Application is forced to shutdown
|
||||
// The difference of the last two is not very clear.
|
||||
if (lParam == 0) {
|
||||
shutdownReason = AppShutdownReason::OSShutdown;
|
||||
} else if (lParam & ENDSESSION_LOGOFF) {
|
||||
shutdownReason = AppShutdownReason::OSSessionEnd;
|
||||
} else if (lParam & (ENDSESSION_CLOSEAPP | ENDSESSION_CRITICAL)) {
|
||||
shutdownReason = AppShutdownReason::OSForceClose;
|
||||
} else {
|
||||
MOZ_DIAGNOSTIC_ASSERT(false,
|
||||
"Received WM_ENDSESSION with unknown flags.");
|
||||
shutdownReason = AppShutdownReason::OSForceClose;
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
case MOZ_WM_APP_QUIT: {
|
||||
if (shutdownReason == AppShutdownReason::Unknown) {
|
||||
// TODO: We do not expect that these days anybody sends us
|
||||
// MOZ_WM_APP_QUIT, see bug 1827807.
|
||||
shutdownReason = AppShutdownReason::WinUnexpectedMozQuit;
|
||||
}
|
||||
// Let's fake a shutdown sequence without actually closing windows etc.
|
||||
// to avoid Windows killing us in the middle. A proper shutdown would
|
||||
// require having a chance to pump some messages. Unfortunately
|
||||
// Windows won't let us do that. Bug 212316.
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
mozilla::services::GetObserverService();
|
||||
const char16_t* syncShutdown = u"syncShutdown";
|
||||
const char16_t* quitType = GetQuitType();
|
||||
|
||||
AppShutdown::Init(AppShutdownMode::Normal, 0, shutdownReason);
|
||||
|
||||
obsServ->NotifyObservers(nullptr, "quit-application-granted",
|
||||
syncShutdown);
|
||||
obsServ->NotifyObservers(nullptr, "quit-application-forced", nullptr);
|
||||
|
||||
AppShutdown::OnShutdownConfirmed();
|
||||
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownConfirmed,
|
||||
quitType);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown,
|
||||
nullptr);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown,
|
||||
nullptr);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown, nullptr);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM, nullptr);
|
||||
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry,
|
||||
nullptr);
|
||||
|
||||
AppShutdown::DoImmediateExit();
|
||||
MOZ_ASSERT_UNREACHABLE("Our process was supposed to exit.");
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SYSCOLORCHANGE:
|
||||
// No need to invalidate layout for system color changes, but we need to
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsAppRunner.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsICertStorage.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
|
@ -193,10 +194,12 @@ wchar_t* CopyPathIntoNewWCString(nsIFile* aFile) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void AppShutdown::Init(AppShutdownMode aMode, int aExitCode) {
|
||||
void AppShutdown::Init(AppShutdownMode aMode, int aExitCode,
|
||||
AppShutdownReason aReason) {
|
||||
if (sShutdownMode == AppShutdownMode::Normal) {
|
||||
sShutdownMode = aMode;
|
||||
}
|
||||
AppShutdown::AnnotateShutdownReason(aReason);
|
||||
|
||||
sExitCode = aExitCode;
|
||||
|
||||
|
@ -304,6 +307,36 @@ bool AppShutdown::IsRestarting() {
|
|||
return sShutdownMode == AppShutdownMode::Restart;
|
||||
}
|
||||
|
||||
void AppShutdown::AnnotateShutdownReason(AppShutdownReason aReason) {
|
||||
auto key = CrashReporter::Annotation::ShutdownReason;
|
||||
nsCString reasonStr;
|
||||
switch (aReason) {
|
||||
case AppShutdownReason::AppClose:
|
||||
reasonStr = "AppClose"_ns;
|
||||
break;
|
||||
case AppShutdownReason::AppRestart:
|
||||
reasonStr = "AppRestart"_ns;
|
||||
break;
|
||||
case AppShutdownReason::OSForceClose:
|
||||
reasonStr = "OSForceClose"_ns;
|
||||
break;
|
||||
case AppShutdownReason::OSSessionEnd:
|
||||
reasonStr = "OSSessionEnd"_ns;
|
||||
break;
|
||||
case AppShutdownReason::OSShutdown:
|
||||
reasonStr = "OSShutdown"_ns;
|
||||
break;
|
||||
case AppShutdownReason::WinUnexpectedMozQuit:
|
||||
reasonStr = "WinUnexpectedMozQuit"_ns;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("We should know the given reason for shutdown.");
|
||||
reasonStr = "Unknown"_ns;
|
||||
break;
|
||||
}
|
||||
CrashReporter::AnnotateCrashReport(key, reasonStr);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool sNotifyingShutdownObservers = false;
|
||||
static bool sAdvancingShutdownPhase = false;
|
||||
|
|
|
@ -19,6 +19,23 @@ enum class AppShutdownMode {
|
|||
Restart,
|
||||
};
|
||||
|
||||
enum class AppShutdownReason {
|
||||
// No reason.
|
||||
Unknown,
|
||||
// Normal application shutdown.
|
||||
AppClose,
|
||||
// The application wants to restart.
|
||||
AppRestart,
|
||||
// The OS is force closing us.
|
||||
OSForceClose,
|
||||
// The user is logging off from the OS session, the system may stay alive.
|
||||
OSSessionEnd,
|
||||
// The system is shutting down (and maybe restarting).
|
||||
OSShutdown,
|
||||
// We unexpectedly received MOZ_WM_APP_QUIT, see bug 1827807.
|
||||
WinUnexpectedMozQuit,
|
||||
};
|
||||
|
||||
class AppShutdown {
|
||||
public:
|
||||
static ShutdownPhase GetCurrentShutdownPhase();
|
||||
|
@ -36,9 +53,11 @@ class AppShutdown {
|
|||
static void SaveEnvVarsForPotentialRestart();
|
||||
|
||||
/**
|
||||
* Init the shutdown with the requested shutdown mode and exit code.
|
||||
* Init the shutdown with the requested shutdown mode, exit code and optional
|
||||
* a reason (if missing it will be derived from aMode).
|
||||
*/
|
||||
static void Init(AppShutdownMode aMode, int aExitCode);
|
||||
static void Init(AppShutdownMode aMode, int aExitCode,
|
||||
AppShutdownReason aReason);
|
||||
|
||||
/**
|
||||
* Confirm that we are in fact going to be shutting down.
|
||||
|
@ -109,6 +128,11 @@ class AppShutdown {
|
|||
#endif
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set the shutdown reason annotation.
|
||||
*/
|
||||
static void AnnotateShutdownReason(AppShutdownReason aReason);
|
||||
|
||||
/**
|
||||
* This will perform a fast shutdown via _exit(0) or similar if the user's
|
||||
* prefs are configured to do so at this phase.
|
||||
|
|
Загрузка…
Ссылка в новой задаче