diff options
Diffstat (limited to 'indra/newview/llappviewer.cpp')
| -rw-r--r-- | indra/newview/llappviewer.cpp | 149 |
1 files changed, 114 insertions, 35 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index bfd8b1dcc7..9a421972e5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -216,7 +216,6 @@ #include "llfloatersimplesnapshot.h" #include "llfloatersnapshot.h" #include "llsidepanelinventory.h" -#include "llatmosphere.h" // includes for idle() idleShutdown() #include "llviewercontrol.h" @@ -1232,15 +1231,15 @@ bool LLAppViewer::init() /// Tell the Coprocedure manager how to discover and store the pool sizes // what I wanted LLCoprocedureManager::getInstance()->setPropertyMethods( - boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), - boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); + std::bind(&LLControlGroup::getU32, std::ref(gSavedSettings), std::placeholders::_1), + std::bind(&LLControlGroup::declareU32, std::ref(gSavedSettings), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, LLControlVariable::PERSIST_ALWAYS)); // TODO: consider moving proxy initialization here or LLCopocedureManager after proxy initialization, may be implement // some other protection to make sure we don't use network before initializng proxy /*----------------------------------------------------------------------*/ // 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); @@ -1347,6 +1346,7 @@ bool LLAppViewer::frame() bool LLAppViewer::doFrame() { + resumeMainloopTimeout("Main:doFrameStart"); #ifdef LL_DISCORD { LL_PROFILE_ZONE_NAMED("discord_callbacks"); @@ -1430,12 +1430,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 @@ -1471,6 +1473,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! } @@ -1482,7 +1485,7 @@ bool LLAppViewer::doFrame() { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df resumeMainloopTimeout"); - resumeMainloopTimeout(); + resumeMainloopTimeout("df idle"); } } @@ -1497,7 +1500,7 @@ bool LLAppViewer::doFrame() } disconnectViewer(); - resumeMainloopTimeout(); + resumeMainloopTimeout("df snapshot n disconnect"); } // Render scene. @@ -1638,17 +1641,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; @@ -1657,6 +1663,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(); @@ -1700,8 +1711,6 @@ void LLAppViewer::flushLFSIO() bool LLAppViewer::cleanup() { - LLAtmosphere::cleanupClass(); - //ditch LLVOAvatarSelf instance gAgentAvatarp = NULL; @@ -2304,7 +2313,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); + } } } @@ -3148,7 +3172,7 @@ bool LLAppViewer::initWindow() // Need to load feature table before cheking to start watchdog. bool use_watchdog = false; - int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); + S32 watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); if (watchdog_enabled_setting == -1) { use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled"); @@ -3167,7 +3191,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(); @@ -3622,10 +3657,15 @@ void LLAppViewer::writeSystemInfo() if (! gDebugInfo.has("Dynamic") ) gDebugInfo["Dynamic"] = LLSD::emptyMap(); -#if LL_WINDOWS && !LL_BUGSPLAT +#if LL_DARWIN + // crash processing in CrashMetadataSingleton reads SLLog + gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.crash"); +#elif LL_WINDOWS && !LL_BUGSPLAT gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log"); #else - //Not ideal but sufficient for good reporting. + // Far from ideal, especially when multiple instances get involved. + // Note that attachmentsForBugSplat expects .old extendion. + // Todo: improve. gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.old"); //LLError::logFileName(); #endif @@ -3948,7 +3988,7 @@ void LLAppViewer::processMarkerFiles() #if LL_WINDOWS && LL_BUGSPLAT // bugsplat will set correct state in bugsplatSendLog // Might be more accurate to rename this one into 'unknown' - gLastExecEvent = LAST_EXEC_FROZE; + gLastExecEvent = LAST_EXEC_UNKNOWN; #else gLastExecEvent = LAST_EXEC_OTHER_CRASH; #endif // LL_WINDOWS @@ -3994,7 +4034,8 @@ void LLAppViewer::processMarkerFiles() { if (markerIsSameVersion(logout_marker_file)) { - gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; + // Either froze, got killed or somehow crash was not caught + gLastExecEvent = LAST_EXEC_LOGOUT_UNKNOWN; LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL; } else @@ -4032,6 +4073,22 @@ void LLAppViewer::processMarkerFiles() } LLAPRFile::remove(error_marker_file); } + +#if LL_DARWIN + if (!mSecondInstance && gLastExecEvent != LAST_EXEC_NORMAL) + { + // While windows reports crashes immediately, mac reports next run and + // may take a while to trigger crash report so it has a special file. + // Remove .crash file if exists + std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + "SecondLife.old"); + std::string crash_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + "SecondLife.crash"); + LLFile::remove(crash_log_file); + // Rename ".old" log file to ".crash" + LLFile::rename(old_log_file, crash_log_file); + } +#endif } void LLAppViewer::removeMarkerFiles() @@ -4125,6 +4182,7 @@ void LLAppViewer::requestQuit() return; } + pingMainloopTimeout("Main:qMetrics"); // Try to send metrics back to the grid metricsSend(!gDisconnected); @@ -4140,6 +4198,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) @@ -4148,6 +4207,7 @@ void LLAppViewer::requestQuit() gFloaterView->closeAllChildren(true); mClosingFloaters = true; } + pingMainloopTimeout("Main:qStats"); // Send preferences once, when exiting bool include_preferences = true; @@ -4155,6 +4215,7 @@ void LLAppViewer::requestQuit() gLogoutTimer.reset(); mQuitRequested = true; + pingMainloopTimeout("Main:LoggingOut"); } static bool finish_quit(const LLSD& notification, const LLSD& response) @@ -4386,6 +4447,8 @@ bool LLAppViewer::initCache() LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL; gSavedSettings.setString("CacheLocation", ""); gSavedSettings.setString("CacheLocationTopFolder", ""); + gSavedSettings.setString("NewCacheLocation", ""); + gSavedSettings.setString("NewCacheLocationTopFolder", ""); } const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); @@ -4438,7 +4501,7 @@ bool LLAppViewer::initCache() return true; } -void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb) +void LLAppViewer::addOnIdleCallback(const std::function<void()>& cb) { gMainloopWork.post(cb); } @@ -5433,6 +5496,7 @@ void LLAppViewer::outOfMemorySoftQuit() LLLFSThread::sLocal->pause(); gLogoutTimer.reset(); mQuitRequested = true; + destroyMainloopTimeout(); LLError::LLUserWarningMsg::showOutOfMemory(); } @@ -5800,12 +5864,12 @@ void LLAppViewer::forceExceptionThreadCrash() thread->start(); } -void LLAppViewer::initMainloopTimeout(std::string_view state, F32 secs) +void LLAppViewer::initMainloopTimeout(std::string_view state) { if (!mMainloopTimeout) { - mMainloopTimeout = new LLWatchdogTimeout(); - resumeMainloopTimeout(state, secs); + mMainloopTimeout = new LLWatchdogTimeout("mainloop"); + resumeMainloopTimeout(state); } } @@ -5818,17 +5882,11 @@ void LLAppViewer::destroyMainloopTimeout() } } -void LLAppViewer::resumeMainloopTimeout(std::string_view state, F32 secs) +void LLAppViewer::resumeMainloopTimeout(std::string_view state) { if (mMainloopTimeout) { - if (secs < 0.0f) - { - static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60.f); - secs = mainloop_timeout; - } - - mMainloopTimeout->setTimeout(secs); + mMainloopTimeout->setTimeout(getMainloopTimeoutSec()); mMainloopTimeout->start(state); } } @@ -5841,27 +5899,48 @@ void LLAppViewer::pauseMainloopTimeout() } } -void LLAppViewer::pingMainloopTimeout(std::string_view state, F32 secs) +void LLAppViewer::pingMainloopTimeout(std::string_view state) { LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; if (mMainloopTimeout) { - if (secs < 0.0f) - { - static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60); - secs = mainloop_timeout; - } - - mMainloopTimeout->setTimeout(secs); + mMainloopTimeout->setTimeout(getMainloopTimeoutSec()); mMainloopTimeout->ping(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) + { + // consider making this value match 'disconnected' timout. + static LLCachedControl<F32> mainloop_started(gSavedSettings, "MainloopTimeoutStarted", 60.f); + return mainloop_started(); + } + else + { + static LLCachedControl<F32> mainloop_default(gSavedSettings, "MainloopTimeoutDefault", 120.f); + return mainloop_default(); + } +} + 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(); |
