summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp4
-rw-r--r--indra/llwindow/llwindowcallbacks.h2
-rw-r--r--indra/llwindow/llwindowwin32.cpp61
-rw-r--r--indra/llwindow/llwindowwin32.h1
-rw-r--r--indra/newview/llappviewer.cpp76
-rw-r--r--indra/newview/llappviewer.h2
-rw-r--r--indra/newview/llviewerwindow.cpp21
-rw-r--r--indra/newview/llviewerwindow.h1
8 files changed, 152 insertions, 16 deletions
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index 7331f50ba0..6267433751 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -68,6 +68,10 @@ void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
return;
}
+void LLWindowCallbacks::handlePreCloseRequest()
+{
+}
+
bool LLWindowCallbacks::handleCloseRequest(LLWindow *window, bool from_user)
{
//allow the window to close
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index 59dcdd3ade..457087448f 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -41,6 +41,8 @@ public:
virtual bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
virtual bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleMouseLeave(LLWindow *window);
+ // Called before close request is processed (ex: to create marker file in case OS is about to kill app).
+ virtual void handlePreCloseRequest();
// return true to allow window to close, which will then cause handleQuit to be called
virtual bool handleCloseRequest(LLWindow *window, bool from_user);
virtual bool handleSessionExit(LLWindow* window);
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 7e956983d0..dd4f638767 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -508,6 +508,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
:
LLWindow(callbacks, fullscreen, flags),
mAbsoluteCursorPosition(false),
+ mReceivedSCClose(false),
mMaxGLVersion(max_gl_version),
mMaxCores(max_cores)
{
@@ -2524,8 +2525,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_SYSCOMMAND:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SYSCOMMAND");
- switch (w_param)
+ switch (w_param & 0xFFF0)
{
+ case SC_CLOSE:
+ // User clicked close from system menu/taskbar or 'end process' from task manager
+ // Do nothing, will cause WM_CLOSE.
+ // If we don't get this message before WM_CLOSE, we are likely getting
+ // a kill from some external program. Win11 task manager Does cause SC_CLOSE.
+ window_imp->mReceivedSCClose = true;
+ break;
case SC_KEYMENU:
// Disallow the ALT key from triggering the default system menu.
return 0;
@@ -2540,9 +2548,30 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_CLOSE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CLOSE");
- // todo: WM_CLOSE can be caused by user and by task manager,
- // distinguish these cases.
- // For now assume it is always user.
+
+ window_imp->mCallbacks->handlePreCloseRequest(); // mark app as potentially closing
+ if (!window_imp->mReceivedSCClose)
+ {
+ // Some external program is trying to close the app.
+ // Assume that it's going to destroy process if it fails
+ // and try to fast-quit without confirmation or cleanup.
+ window_imp->post([=]()
+ {
+ // Check if app needs cleanup or can be closed immediately.
+ if (window_imp->mCallbacks->handleSessionExit(window_imp))
+ {
+ // Get the app to initiate cleanup.
+ window_imp->mCallbacks->handleQuit(window_imp);
+ }
+ });
+ return 0;
+ }
+ window_imp->mReceivedSCClose = false;
+
+ // There is no way to tell the difference between a user issued
+ // WM_CLOSE or task manager's WM_CLOSE.
+ // Assume it is a user and ask for confirmation, but create a marker file.
+ // If App keeps doing something after a second, or gets 'destroy' message clear the marker.
window_imp->post([=]()
{
// Will the app allow the window to close?
@@ -2564,6 +2593,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
}
return 0;
}
+ case WM_NCDESTROY:
+ LL_INFOS("Window") << "Received WM_NCDESTROY" << LL_ENDL;
+ break;
+ case WM_WTSSESSION_CHANGE:
+ {
+ // Detects Remote Desktop disconnects, fast user switching, session logoff
+ // w_param: WTS_CONSOLE_CONNECT, WTS_CONSOLE_DISCONNECT, WTS_SESSION_LOGOFF, etc.
+ LL_INFOS("Window") << "Received WM_WTSSESSION_CHANGE with wParam: " << (U32)w_param << LL_ENDL;
+ break;
+ }
case WM_QUERYENDSESSION:
{
// Generally means that OS is going to shut down or user is going to log off.
@@ -2585,6 +2624,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|| (end_session_flags & ENDSESSION_CRITICAL) // will shutdown regardless of app state
|| (end_session_flags & ENDSESSION_LOGOFF)) // logoff, can delay shutdown
{
+ window_imp->mCallbacks->handlePreCloseRequest(); // mark app as closing
window_imp->post([=]()
{
LL_INFOS("Window") << "Shutting down due to session terminating" << LL_ENDL;
@@ -3318,7 +3358,18 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_DISPLAYCHANGE:
{
- WINDOW_IMP_POST(window_imp->mCallbacks->handleDisplayChanged());
+ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_DISPLAYCHANGE");
+ window_imp->post([=]() {
+ window_imp->mCallbacks->handleDisplayChanged();
+ // Note: WM_DISPLAYCHANGE was passing to WM_SETFOCUS
+ // which might have been unintended and was messing with zones.
+ // handleFocus was copied over and return 0 added, but
+ // handleFocus might be not needed here.
+ // handleFocus resets mouse, closes popups and keys, which
+ // we probablt should do on 'display change'.
+ window_imp->mCallbacks->handleFocus(window_imp);
+ });
+ return 0;
}
case WM_SETFOCUS:
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index afff3d5cb6..defa90d1a3 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -238,6 +238,7 @@ protected:
LPWSTR mIconResource;
LPWSTR mIconSmallResource;
bool mInputProcessingPaused;
+ bool mReceivedSCClose; // received SC_CLOSE and expecting WM_CLOSE
// The following variables are for Language Text Input control.
// They are all static, since one context is shared by all LLWindowWin32
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 4aaf8411cc..631804e13e 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -384,6 +384,7 @@ const std::string START_MARKER_FILE_NAME("SecondLife.start_marker");
const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
const std::string WATCHDOG_MARKER_FILE_NAME("SecondLife.watchdog_marker");
+const std::string CLOSE_EVENT_MARKER_FILE_NAME("SecondLife.close_marker");
static std::string gLaunchFileOnQuit;
//----------------------------------------------------------------------------
@@ -4121,6 +4122,7 @@ void LLAppViewer::processMarkerFiles()
// Bugsplat will set correct state in bugsplatSendLog.
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
std::string watchdog_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, WATCHDOG_MARKER_FILE_NAME);
+ std::string close_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, CLOSE_EVENT_MARKER_FILE_NAME);
if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
{
S32 marker_code = getMarkerErrorCode(error_marker_file);
@@ -4150,20 +4152,16 @@ void LLAppViewer::processMarkerFiles()
LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
}
LLAPRFile::remove(error_marker_file);
- if (LLAPRFile::isExist(watchdog_marker_file, NULL, LL_APR_RB))
- {
- // If viewer crashed after a freeze was detected,
- // crash still takes precendence. Just clear watchdog.
- removeWatchdogMarker();
- }
}
else
{
- // so only check watchdog marker if there is no error marker.
- if (LLAPRFile::isExist(watchdog_marker_file, NULL, LL_APR_RB))
+ if (LAST_EXEC_UNKNOWN == gLastExecEvent
+ || LAST_EXEC_LOGOUT_UNKNOWN == gLastExecEvent)
{
- if (LAST_EXEC_UNKNOWN == gLastExecEvent
- || LAST_EXEC_LOGOUT_UNKNOWN == gLastExecEvent)
+ // If viewer crashed after a freeze was detected,
+ // crash still takes precendence.
+ // So only check watchdog marker if there is no error marker.
+ if (LLAPRFile::isExist(watchdog_marker_file, NULL, LL_APR_RB))
{
// watchdog marker gets created if we detect a freeze,
// so if viwer did not stop gracefully, and we know it wasn't a crash,
@@ -4175,9 +4173,35 @@ void LLAppViewer::processMarkerFiles()
<< LL_ENDL;
}
}
- removeWatchdogMarker();
+ // If 'close' marker is found, viewer either started shutdown but
+ // failed, or viewer got killed by task manager.
+ // Marker does not indicate that viewer was closed or is closing,
+ // just that 'close' was requested before viewer died.
+ else if (LLAPRFile::isExist(close_marker_file, NULL, LL_APR_RB))
+ {
+ // For now treat as 'other' cause.
+ // Unfortunately we can't for certain distinguish task
+ // manager's case from other shutdown problems, so we
+ // have to report both.
+ // Todo: if this bears noticeable fruits, make a new state later.
+ // New categories need server/web side support.
+ if (markerIsSameVersion(close_marker_file))
+ {
+ gLastExecEvent = LAST_EXEC_UNKNOWN == gLastExecEvent ? LAST_EXEC_OTHER_CRASH : LAST_EXEC_LOGOUT_CRASH;
+ LL_INFOS("MarkerFile") << "'Close' marker '" << close_marker_file << "' found, setting LastExecEvent to CRASH"
+ << LL_ENDL;
+ }
+ }
}
}
+ if (LLAPRFile::isExist(watchdog_marker_file, NULL, LL_APR_RB))
+ {
+ removeWatchdogMarker();
+ }
+ if (LLAPRFile::isExist(close_marker_file, NULL, LL_APR_RB))
+ {
+ removeCloseRequestMarker();
+ }
#if LL_DARWIN
if (!mSecondInstance && gLastExecEvent != LAST_EXEC_NORMAL)
@@ -4221,6 +4245,7 @@ void LLAppViewer::removeMarkerFiles()
{
LL_WARNS("MarkerFile") << "logout marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
}
+ removeCloseRequestMarker();
removeWatchdogMarker();
}
else
@@ -5609,6 +5634,34 @@ bool LLAppViewer::errorMarkerExists() const
return LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB);
}
+void LLAppViewer::createCloseRequestMarker() const
+{
+ // WINDOW THREAD! since we need this to act fast.
+ // This does not indicate that viewer was closed or is closing,
+ // but that 'close' was requested.
+ if (!mSecondInstance)
+ {
+ std::string close_marker = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, CLOSE_EVENT_MARKER_FILE_NAME);
+
+ LLAPRFile file;
+ file.open(close_marker, LL_APR_WB);
+ if (file.getFileHandle())
+ {
+ recordMarkerVersion(file);
+ file.close();
+ }
+ }
+}
+
+void LLAppViewer::removeCloseRequestMarker() const
+{
+ if (!mSecondInstance)
+ {
+ std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, CLOSE_EVENT_MARKER_FILE_NAME);
+ LLFile::remove(error_marker_file);
+ }
+}
+
void LLAppViewer::createWatchdogMarker() const
{
if (!mSecondInstance)
@@ -5624,6 +5677,7 @@ void LLAppViewer::createWatchdogMarker() const
}
}
}
+
void LLAppViewer::removeWatchdogMarker() const
{
if (!mSecondInstance)
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index d76e5015e9..87c885e4be 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -254,6 +254,8 @@ public:
void createErrorMarker(eLastExecEvent error_code) const;
bool errorMarkerExists() const;
+ void createCloseRequestMarker() const;
+ void removeCloseRequestMarker() const;
void createWatchdogMarker() const;
void removeWatchdogMarker() const;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 8695b96952..369a887102 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -38,6 +38,7 @@
#include "llagent.h"
#include "llagentcamera.h"
+#include "llcallbacklist.h"
#include "llcommandhandler.h"
#include "llcommunicationchannel.h"
#include "llfloaterreg.h"
@@ -1466,12 +1467,32 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window)
LLToolTipMgr::instance().blockToolTips();
}
+void LLViewerWindow::handlePreCloseRequest()
+{
+ // WINDOW THREAD! since we need this to act fast.
+ if (!LLApp::isExiting() && !LLApp::isStopped())
+ {
+ LLAppViewer::instance()->createCloseRequestMarker();
+ }
+
+}
+
bool LLViewerWindow::handleCloseRequest(LLWindow *window, bool from_user)
{
if (!LLApp::isExiting() && !LLApp::isStopped())
{
if (from_user)
{
+ // Task naamger kills viewer after 1 second, 3 seconds
+ // is overkill, but decided to be on a safe side.
+ doAfterInterval([]()
+ {
+ // if user quits, marker will be cleaned by cleanup,
+ // if user cancels quit, marker will be cleaned here,
+ // but if task manager kills us, marker stays.
+ LLAppViewer::instance()->removeCloseRequestMarker();
+ }, 3.0f);
+
// User has indicated they want to close, but we may need to ask
// about modified documents.
LLAppViewer::instance()->userQuit();
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index ec28a3fc4a..ff5da371ec 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -202,6 +202,7 @@ public:
/*virtual*/ bool handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended
/*virtual*/ bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ /*virtual*/ void handlePreCloseRequest();
/*virtual*/ bool handleCloseRequest(LLWindow *window, bool from_user);
/*virtual*/ bool handleSessionExit(LLWindow* window);
/*virtual*/ void handleQuit(LLWindow *window);