summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r--indra/newview/llappviewer.cpp239
1 files changed, 134 insertions, 105 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c34441932d..1db62f2fab 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -98,6 +98,11 @@
#include "llurlmatch.h"
#include "lltextutil.h"
#include "lllogininstance.h"
+#include "llvvmquery.h"
+
+#if LL_VELOPACK
+#include "llvelopack.h"
+#endif
#include "llprogressview.h"
#include "llvocache.h"
#include "lldiskcache.h"
@@ -220,7 +225,6 @@
#include "llfloatersimplesnapshot.h"
#include "llfloatersnapshot.h"
#include "llsidepanelinventory.h"
-#include "llatmosphere.h"
// includes for idle() idleShutdown()
#include "llviewercontrol.h"
@@ -396,10 +400,6 @@ const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
static std::string gLaunchFileOnQuit;
-// Used on Win32 for other apps to identify our window (eg, win_setup)
-const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
-
-
//----------------------------------------------------------------------------
// List of entries from strings.xml to always replace
@@ -680,7 +680,6 @@ LLAppViewer::LLAppViewer()
mPurgeCacheOnExit(false),
mPurgeUserDataOnExit(false),
mSecondInstance(false),
- mUpdaterNotFound(false),
mSavedFinalSnapshot(false),
mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded.
mQuitRequested(false),
@@ -1136,68 +1135,17 @@ bool LLAppViewer::init()
gGLActive = false;
-#if 0 // LL_RELEASE_FOR_DOWNLOAD && !LL_LINUX
- // Skip updater if this is a non-interactive instance
+//#if LL_RELEASE_FOR_DOWNLOAD
+ // Launch VVM update check
if (!gSavedSettings.getBOOL("CmdLineSkipUpdater") && !gNonInteractive)
{
- LLProcess::Params updater;
- updater.desc = "updater process";
- // Because it's the updater, it MUST persist beyond the lifespan of the
- // viewer itself.
- updater.autokill = false;
- std::string updater_file;
-#if LL_WINDOWS
- updater_file = "SLVersionChecker.exe";
- updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);
-#elif LL_DARWIN
- updater_file = "SLVersionChecker";
- updater.executable = gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", updater_file);
-#else
- updater_file = "SLVersionChecker";
- updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);
-#endif
- // add LEAP mode command-line argument to whichever of these we selected
- updater.args.add("leap");
- // UpdaterServiceSettings
- if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
- {
- // Befor first login, treat this as 'manual' updates,
- // updater won't install anything, but required updates
- updater.args.add("0");
- }
- else
- {
- updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
- }
- // channel
- updater.args.add(LLVersionInfo::instance().getChannel());
- // testok
- updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
- // ForceAddressSize
- updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
-
- try
- {
- // Run the updater. An exception from launching the updater should bother us.
- LLLeap::create(updater, true);
- mUpdaterNotFound = false;
- }
- catch (...)
- {
- LLUIString details = LLNotifications::instance().getGlobalString("LLLeapUpdaterFailure");
- details.setArg("[UPDATER_APP]", updater_file);
- OSMessageBox(
- details.getString(),
- LLStringUtil::null,
- OSMB_OK);
- mUpdaterNotFound = true;
- }
+ initVVMUpdateCheck();
}
else
{
LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL;
}
-#endif //LL_RELEASE_FOR_DOWNLOAD
+//#endif //LL_RELEASE_FOR_DOWNLOAD
{
// Iterate over --leap command-line options. But this is a bit tricky: if
@@ -1255,15 +1203,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);
@@ -1374,6 +1322,8 @@ bool LLAppViewer::frame()
bool LLAppViewer::doFrame()
{
+ resumeMainloopTimeout("Main:doFrameStart");
+
U32 fpsLimitMaxFps = (U32)gSavedSettings.getU32("MaxFPS");
if(fpsLimitMaxFps > 120) fpsLimitMaxFps = 0;
@@ -1464,12 +1414,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
@@ -1505,6 +1457,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!
}
@@ -1516,7 +1469,7 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df resumeMainloopTimeout");
- resumeMainloopTimeout();
+ resumeMainloopTimeout("df idle");
}
}
@@ -1531,7 +1484,7 @@ bool LLAppViewer::doFrame()
}
disconnectViewer();
- resumeMainloopTimeout();
+ resumeMainloopTimeout("df snapshot n disconnect");
}
// Render scene.
@@ -1696,17 +1649,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;
@@ -1715,6 +1671,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();
@@ -1758,7 +1719,15 @@ void LLAppViewer::flushLFSIO()
bool LLAppViewer::cleanup()
{
- LLAtmosphere::cleanupClass();
+#if LL_VELOPACK
+ // Apply any pending Velopack update before shutdown
+ if (velopack_is_update_pending())
+ {
+ LL_INFOS("AppInit") << "Applying pending Velopack update on shutdown..." << LL_ENDL;
+ velopack_apply_pending_update(velopack_should_restart_after_update());
+ }
+ velopack_cleanup();
+#endif
//ditch LLVOAvatarSelf instance
gAgentAvatarp = NULL;
@@ -2365,7 +2334,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);
+ }
}
}
@@ -3184,7 +3168,7 @@ bool LLAppViewer::initWindow()
LLViewerWindow::Params window_params;
window_params
.title(gWindowTitle)
- .name(VIEWER_WINDOW_CLASSNAME)
+ .name(sWindowClass)
.x(gSavedSettings.getS32("WindowX"))
.y(gSavedSettings.getS32("WindowY"))
.width(gSavedSettings.getU32("WindowWidth"))
@@ -3209,7 +3193,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");
@@ -3228,7 +3212,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();
@@ -3298,16 +3293,6 @@ bool LLAppViewer::initWindow()
return true;
}
-bool LLAppViewer::isUpdaterMissing()
-{
- return mUpdaterNotFound;
-}
-
-bool LLAppViewer::waitForUpdater()
-{
- return !gSavedSettings.getBOOL("CmdLineSkipUpdater") && !mUpdaterNotFound && !gNonInteractive;
-}
-
void LLAppViewer::writeDebugInfo(bool isStatic)
{
#if LL_WINDOWS && LL_BUGSPLAT
@@ -3684,10 +3669,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
@@ -4010,7 +4000,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
@@ -4056,7 +4046,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
@@ -4094,6 +4085,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()
@@ -4187,6 +4194,7 @@ void LLAppViewer::requestQuit()
return;
}
+ pingMainloopTimeout("Main:qMetrics");
// Try to send metrics back to the grid
metricsSend(!gDisconnected);
@@ -4202,6 +4210,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)
@@ -4210,6 +4219,7 @@ void LLAppViewer::requestQuit()
gFloaterView->closeAllChildren(true);
mClosingFloaters = true;
}
+ pingMainloopTimeout("Main:qStats");
// Send preferences once, when exiting
bool include_preferences = true;
@@ -4217,6 +4227,7 @@ void LLAppViewer::requestQuit()
gLogoutTimer.reset();
mQuitRequested = true;
+ pingMainloopTimeout("Main:LoggingOut");
}
static bool finish_quit(const LLSD& notification, const LLSD& response)
@@ -4448,6 +4459,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);
@@ -4500,7 +4513,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);
}
@@ -5495,6 +5508,7 @@ void LLAppViewer::outOfMemorySoftQuit()
LLLFSThread::sLocal->pause();
gLogoutTimer.reset();
mQuitRequested = true;
+ destroyMainloopTimeout();
LLError::LLUserWarningMsg::showOutOfMemory();
}
@@ -5860,12 +5874,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);
}
}
@@ -5878,17 +5892,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);
}
}
@@ -5901,27 +5909,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();