summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@geenzo.com>2026-02-24 11:34:08 -0500
committerJonathan "Geenz" Goodman <geenz@geenzo.com>2026-02-24 11:34:08 -0500
commit276cef06232cc3331231fa2155e2eebf6517dfd5 (patch)
treed15cfdd8c40370b6d1b5300545c4ed8dc866b46b /indra/newview/llappviewer.cpp
parenta6b978b3e00f2e7e186b97d8a4997374adecdafc (diff)
parent44e21aa718211cf34a59a036f2831c2e80fef8e1 (diff)
Merge branch 'release/2026.01' into project/one-click
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r--indra/newview/llappviewer.cpp68
1 files changed, 61 insertions, 7 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 701ae189bd..47c517eb5b 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1194,7 +1194,7 @@ bool LLAppViewer::init()
/*----------------------------------------------------------------------*/
// nat 2016-06-29 moved the following here from the former mainLoop().
- mMainloopTimeout = new LLWatchdogTimeout();
+ mMainloopTimeout = new LLWatchdogTimeout("mainloop");
// Create IO Pump to use for HTTP Requests.
gServicePump = new LLPumpIO(gAPRPoolp);
@@ -1301,6 +1301,7 @@ bool LLAppViewer::frame()
bool LLAppViewer::doFrame()
{
+ resumeMainloopTimeout("Main:doFrameStart");
#ifdef LL_DISCORD
{
LL_PROFILE_ZONE_NAMED("discord_callbacks");
@@ -1384,12 +1385,14 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df mainloop");
+ pingMainloopTimeout("df mainloop");
// canonical per-frame event
mainloop.post(newFrame);
}
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df suspend");
+ pingMainloopTimeout("df suspend");
// give listeners a chance to run
llcoro::suspend();
// if one of our coroutines threw an uncaught exception, rethrow it now
@@ -1425,6 +1428,7 @@ bool LLAppViewer::doFrame()
{
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df pauseMainloopTimeout");
+ pingMainloopTimeout("df idle"); // So that it will be aware of last state.
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
}
@@ -1436,7 +1440,7 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df resumeMainloopTimeout");
- resumeMainloopTimeout();
+ resumeMainloopTimeout("df idle");
}
}
@@ -1451,7 +1455,7 @@ bool LLAppViewer::doFrame()
}
disconnectViewer();
- resumeMainloopTimeout();
+ resumeMainloopTimeout("df snapshot n disconnect");
}
// Render scene.
@@ -1592,17 +1596,20 @@ bool LLAppViewer::doFrame()
if (LLApp::isExiting())
{
+ pingMainloopTimeout("Main:qSnapshot");
// Save snapshot for next time, if we made it through initialization
if (STATE_STARTED == LLStartUp::getStartupState())
{
saveFinalSnapshot();
}
+ pingMainloopTimeout("Main:TerminateVoice");
if (LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->terminate();
}
+ pingMainloopTimeout("Main:TerminatePump");
delete gServicePump;
gServicePump = NULL;
@@ -1611,6 +1618,11 @@ bool LLAppViewer::doFrame()
LL_INFOS() << "Exiting main_loop" << LL_ENDL;
}
}LLPerfStats::StatsRecorder::endFrame();
+
+ // Not viewer's fault if something outside frame
+ // pauses viewer (ex: macOS doesn't call oneFrame),
+ // so stop tracking on exit.
+ pauseMainloopTimeout();
LL_PROFILER_FRAME_END;
return ! LLApp::isRunning();
@@ -2265,7 +2277,22 @@ void errorHandler(const std::string& title_string, const std::string& message_st
}
if (!message_string.empty())
{
- OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+ if (on_main_thread())
+ {
+ // Prevent watchdog from killing us while dialog is up.
+ // Can't do pauseMainloopTimeout, since this may be called
+ // from threads and we are not going to need watchdog now.
+ LLAppViewer::instance()->pauseMainloopTimeout();
+
+ // todo: might want to have non-crashing timeout for OOM cases
+ // and needs a way to pause main loop.
+ OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+ LLAppViewer::instance()->resumeMainloopTimeout();
+ }
+ else
+ {
+ OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK);
+ }
}
}
@@ -3128,7 +3155,18 @@ bool LLAppViewer::initWindow()
if (use_watchdog)
{
- LLWatchdog::getInstance()->init();
+ LLWatchdog::getInstance()->init([]()
+ {
+ LLAppViewer* app = LLAppViewer::instance();
+ if (app->logoutRequestSent())
+ {
+ app->createErrorMarker(LAST_EXEC_LOGOUT_FROZE);
+ }
+ else
+ {
+ app->createErrorMarker(LAST_EXEC_FROZE);
+ }
+ });
}
LLNotificationsUI::LLNotificationManager::getInstance();
@@ -4108,6 +4146,7 @@ void LLAppViewer::requestQuit()
return;
}
+ pingMainloopTimeout("Main:qMetrics");
// Try to send metrics back to the grid
metricsSend(!gDisconnected);
@@ -4123,6 +4162,7 @@ void LLAppViewer::requestQuit()
LLHUDManager::getInstance()->sendEffects();
effectp->markDead() ;//remove it.
+ pingMainloopTimeout("Main:qFloaters");
// Attempt to close all floaters that might be
// editing things.
if (gFloaterView)
@@ -4131,6 +4171,7 @@ void LLAppViewer::requestQuit()
gFloaterView->closeAllChildren(true);
mClosingFloaters = true;
}
+ pingMainloopTimeout("Main:qStats");
// Send preferences once, when exiting
bool include_preferences = true;
@@ -4138,6 +4179,7 @@ void LLAppViewer::requestQuit()
gLogoutTimer.reset();
mQuitRequested = true;
+ pingMainloopTimeout("Main:LoggingOut");
}
static bool finish_quit(const LLSD& notification, const LLSD& response)
@@ -5418,6 +5460,7 @@ void LLAppViewer::outOfMemorySoftQuit()
LLLFSThread::sLocal->pause();
gLogoutTimer.reset();
mQuitRequested = true;
+ destroyMainloopTimeout();
LLError::LLUserWarningMsg::showOutOfMemory();
}
@@ -5789,7 +5832,7 @@ void LLAppViewer::initMainloopTimeout(std::string_view state)
{
if (!mMainloopTimeout)
{
- mMainloopTimeout = new LLWatchdogTimeout();
+ mMainloopTimeout = new LLWatchdogTimeout("mainloop");
resumeMainloopTimeout(state);
}
}
@@ -5834,10 +5877,16 @@ void LLAppViewer::pingMainloopTimeout(std::string_view state)
F32 LLAppViewer::getMainloopTimeoutSec() const
{
+ if (isQuitting() || mQuitRequested)
+ {
+ constexpr F32 QUITTING_SECONDS = 240.f;
+ return QUITTING_SECONDS;
+ }
if (LLStartUp::getStartupState() == STATE_STARTED
&& gAgent.getTeleportState() == LLAgent::TELEPORT_NONE)
{
- static LLCachedControl<F32> mainloop_started(gSavedSettings, "MainloopTimeoutStarted", 30.f);
+ // consider making this value match 'disconnected' timout.
+ static LLCachedControl<F32> mainloop_started(gSavedSettings, "MainloopTimeoutStarted", 60.f);
return mainloop_started();
}
else
@@ -5851,6 +5900,11 @@ void LLAppViewer::handleLoginComplete()
{
gLoggedInTime.start();
initMainloopTimeout("Mainloop Init");
+ LLWindow* viewer_window = gViewerWindow->getWindow();
+ if (viewer_window) // in case of a headless client
+ {
+ viewer_window->initWatchdog();
+ }
// Store some data to DebugInfo in case of a freeze.
gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel();