summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llappviewer.cpp956
1 files changed, 555 insertions, 401 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 1c6f099185..becc75203a 100644..100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -30,7 +30,6 @@
// Viewer includes
#include "llversioninfo.h"
-#include "llversionviewer.h"
#include "llfeaturemanager.h"
#include "lluictrlfactory.h"
#include "lltexteditor.h"
@@ -118,17 +117,19 @@
#include "llleap.h"
#include "stringize.h"
+#include "llcoros.h"
// Third party library includes
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
+#include <boost/regex.hpp>
#if LL_WINDOWS
-# include <share.h> // For _SH_DENYWR in initMarkerFile
+# include <share.h> // For _SH_DENYWR in processMarkerFiles
#else
-# include <sys/file.h> // For initMarkerFile support
+# include <sys/file.h> // For processMarkerFiles
#endif
#include "llapr.h"
@@ -221,6 +222,10 @@
#include "llmachineid.h"
#include "llmainlooprepeater.h"
+
+#include "llviewereventrecorder.h"
+
+
// *FIX: These extern globals should be cleaned up.
// The globals either represent state/config/resource-storage of either
// this app, or another 'component' of the viewer. App globals should be
@@ -252,6 +257,7 @@ static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
// viewer.cpp - these are only used in viewer, should be easily moved.
#if LL_DARWIN
+const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer";
extern void init_apple_menu(const char* product);
#endif // LL_DARWIN
@@ -269,6 +275,20 @@ BOOL gShowObjectUpdates = FALSE;
BOOL gUseQuickTime = TRUE;
eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
+S32 gLastExecDuration = -1; // (<0 indicates unknown)
+
+#if LL_WINDOWS
+# define LL_PLATFORM_KEY "win"
+#elif LL_DARWIN
+# define LL_PLATFORM_KEY "mac"
+#elif LL_LINUX
+# define LL_PLATFORM_KEY "lnx"
+#elif LL_SOLARIS
+# define LL_PLATFORM_KEY "sol"
+#else
+# error "Unknown Platform"
+#endif
+const char* gPlatform = LL_PLATFORM_KEY;
LLSD gDebugInfo;
@@ -292,6 +312,10 @@ LLTimer gLogoutTimer;
static const F32 LOGOUT_REQUEST_TIME = 6.f; // this will be cut short by the LogoutReply msg.
F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
+
+S32 gPendingMetricsUploads = 0;
+
+
BOOL gDisconnected = FALSE;
// used to restore texture state after a mode switch
@@ -326,6 +350,7 @@ BOOL gLogoutInProgress = FALSE;
static std::string gArgs;
const int MAX_MARKER_LENGTH = 1024;
const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
+const std::string START_MARKER_FILE_NAME("SecondLife.start_marker");
const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker");
const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
@@ -578,7 +603,8 @@ static void settings_to_globals()
static void settings_modify()
{
LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderDeferred");
- LLPipeline::sRenderDeferred = gSavedSettings.getBOOL("RenderDeferred");
+ LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+ LLPipeline::sRenderDeferred = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred");
LLVOAvatar::sUseImpostors = gSavedSettings.getBOOL("RenderUseImpostors");
LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
@@ -646,7 +672,6 @@ LLAppViewer::LLAppViewer() :
mSecondInstance(false),
mSavedFinalSnapshot(false),
mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded.
- mForceGraphicsDetail(false),
mQuitRequested(false),
mLogoutRequestSent(false),
mYieldTime(-1),
@@ -668,11 +693,13 @@ LLAppViewer::LLAppViewer() :
gLoggedInTime.stop();
LLLoginInstance::instance().setUpdaterService(mUpdater.get());
+ LLLoginInstance::instance().setPlatformInfo(gPlatform, getOSInfo().getOSVersionString());
}
LLAppViewer::~LLAppViewer()
{
delete mSettingsLocationList;
+ LLViewerEventRecorder::instance().~LLViewerEventRecorder();
LLLoginInstance::instance().setUpdaterService(0);
@@ -682,6 +709,15 @@ LLAppViewer::~LLAppViewer()
removeMarkerFile();
}
+class LLUITranslationBridge : public LLTranslationBridge
+{
+public:
+ virtual std::string getString(const std::string &xml_desc)
+ {
+ return LLTrans::getString(xml_desc);
+ }
+};
+
bool LLAppViewer::init()
{
//
@@ -692,6 +728,15 @@ bool LLAppViewer::init()
// we run the "program crashed last time" error handler below.
//
LLFastTimer::reset();
+
+
+#ifdef LL_DARWIN
+ mMainLoopInitialized = false;
+#endif
+
+ // initialize LLWearableType translation bridge.
+ // Memory will be cleaned up in ::cleanupClass()
+ LLWearableType::initClass(new LLUITranslationBridge());
// initialize SSE options
LLVector4a::initClass();
@@ -706,8 +751,10 @@ bool LLAppViewer::init()
// this allows simple skinned file lookups to work
gDirUtilp->setSkinFolder("default", "en");
- initLogging();
+ initLoggingAndGetLastDuration();
+ processMarkerFiles();
+
//
// OK to write stuff to logs now, we've now crash reported if necessary
//
@@ -721,6 +768,7 @@ bool LLAppViewer::init()
//set the max heap size.
initMaxHeapSize() ;
+ LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")*1024*1024) ;
@@ -729,7 +777,7 @@ bool LLAppViewer::init()
logdir += gDirUtilp->getDirDelimiter();
setMiniDumpDir(logdir);
- // Although initLogging() is the right place to mess with
+ // Although initLoggingAndGetLastDuration() is the right place to mess with
// setFatalFunction(), we can't query gSavedSettings until after
// initConfiguration().
S32 rc(gSavedSettings.getS32("QAModeTermCode"));
@@ -786,7 +834,7 @@ bool LLAppViewer::init()
LLUIImageList::getInstance(),
ui_audio_callback,
deferred_ui_audio_callback,
- &LLUI::sGLScaleFactor);
+ &LLUI::getScaleFactor());
LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ;
// NOW LLUI::getLanguage() should work. gDirUtilp must know the language
@@ -1215,40 +1263,57 @@ LLFastTimer::DeclareTimer FTM_FRAME("Frame", true);
bool LLAppViewer::mainLoop()
{
- mMainloopTimeout = new LLWatchdogTimeout();
+#ifdef LL_DARWIN
+ if (!mMainLoopInitialized)
+#endif
+ {
+ mMainloopTimeout = new LLWatchdogTimeout();
+
+ //-------------------------------------------
+ // Run main loop until time to quit
+ //-------------------------------------------
+
+ // Create IO Pump to use for HTTP Requests.
+ gServicePump = new LLPumpIO(gAPRPoolp);
+ LLHTTPClient::setPump(*gServicePump);
+ LLCurl::setCAFile(gDirUtilp->getCAFile());
+
+ // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
+
+ LLVoiceChannel::initClass();
+ LLVoiceClient::getInstance()->init(gServicePump);
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
+
+ joystick = LLViewerJoystick::getInstance();
+ joystick->setNeedsReset(true);
+
+#ifdef LL_DARWIN
+ // Ensure that this section of code never gets called again on OS X.
+ mMainLoopInitialized = true;
+#endif
+ }
+ // As we do not (yet) send data on the mainloop LLEventPump that varies
+ // with each frame, no need to instantiate a new LLSD event object each
+ // time. Obviously, if that changes, just instantiate the LLSD at the
+ // point of posting.
+
+ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+
+ LLSD newFrame;
- //-------------------------------------------
- // Run main loop until time to quit
- //-------------------------------------------
-
- // Create IO Pump to use for HTTP Requests.
- gServicePump = new LLPumpIO(gAPRPoolp);
- LLHTTPClient::setPump(*gServicePump);
- LLCurl::setCAFile(gDirUtilp->getCAFile());
-
- // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
-
- LLVoiceChannel::initClass();
- LLVoiceClient::getInstance()->init(gServicePump);
- LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
- LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
- joystick->setNeedsReset(true);
-
- LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
- // As we do not (yet) send data on the mainloop LLEventPump that varies
- // with each frame, no need to instantiate a new LLSD event object each
- // time. Obviously, if that changes, just instantiate the LLSD at the
- // point of posting.
- LLSD newFrame;
-
+
//LLPrivateMemoryPoolTester::getInstance()->run(false) ;
//LLPrivateMemoryPoolTester::getInstance()->run(true) ;
//LLPrivateMemoryPoolTester::destroy() ;
// Handle messages
+#ifdef LL_DARWIN
+ if (!LLApp::isExiting())
+#else
while (!LLApp::isExiting())
+#endif
{
LLFastTimer _(FTM_FRAME);
LLFastTimer::nextFrame();
@@ -1524,34 +1589,37 @@ bool LLAppViewer::mainLoop()
}
}
- // Save snapshot for next time, if we made it through initialization
- if (STATE_STARTED == LLStartUp::getStartupState())
+ if (LLApp::isExiting())
{
- try
- {
- saveFinalSnapshot();
- }
- catch(std::bad_alloc)
+ // Save snapshot for next time, if we made it through initialization
+ if (STATE_STARTED == LLStartUp::getStartupState())
{
- llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
-
- //stop memory leaking simulation
- LLFloaterMemLeak* mem_leak_instance =
- LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
- if(mem_leak_instance)
+ try
{
- mem_leak_instance->stop() ;
- }
+ saveFinalSnapshot();
+ }
+ catch(std::bad_alloc)
+ {
+ llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
+
+ //stop memory leaking simulation
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
+ {
+ mem_leak_instance->stop() ;
+ }
+ }
}
+
+ delete gServicePump;
+
+ destroyMainloopTimeout();
+
+ llinfos << "Exiting main_loop" << llendflush;
}
-
- delete gServicePump;
- destroyMainloopTimeout();
-
- llinfos << "Exiting main_loop" << llendflush;
-
- return true;
+ return LLApp::isExiting();
}
void LLAppViewer::flushVFSIO()
@@ -1690,19 +1758,7 @@ bool LLAppViewer::cleanup()
gAudiop->setStreamingAudioImpl(NULL);
// shut down the audio subsystem
-
- bool want_longname = false;
- if (gAudiop->getDriverName(want_longname) == "FMOD")
- {
- // This hack exists because fmod likes to occasionally
- // crash or hang forever when shutting down, for no
- // apparent reason.
- llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush;
- }
- else
- {
gAudiop->shutdown();
- }
delete gAudiop;
gAudiop = NULL;
@@ -1775,6 +1831,10 @@ bool LLAppViewer::cleanup()
llinfos << "Cleaning up Objects" << llendflush;
LLViewerObject::cleanupVOClasses();
+
+ LLAvatarAppearance::cleanupClass();
+
+ LLAvatarAppearance::cleanupClass();
LLPostProcess::cleanupClass();
@@ -2014,6 +2074,8 @@ bool LLAppViewer::cleanup()
llinfos << "Cleaning up LLProxy." << llendl;
LLProxy::cleanupClass();
+ LLWearableType::cleanupClass();
+
LLMainLoopRepeater::instance().stop();
//release all private memory pools.
@@ -2097,7 +2159,7 @@ void errorCallback(const std::string &error_string)
LLError::crashAndLoop(error_string);
}
-bool LLAppViewer::initLogging()
+void LLAppViewer::initLoggingAndGetLastDuration()
{
//
// Set up logging defaults for the viewer
@@ -2111,17 +2173,61 @@ bool LLAppViewer::initLogging()
"SecondLife.old");
LLFile::remove(old_log_file);
- // Rename current log file to ".old"
+ // Get name of the log file
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SecondLife.log");
+ /*
+ * Before touching any log files, compute the duration of the last run
+ * by comparing the ctime of the previous start marker file with the ctime
+ * of the last log file.
+ */
+ std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME);
+ llstat start_marker_stat;
+ llstat log_file_stat;
+ std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below
+ int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat);
+ int log_stat_result = LLFile::stat(log_file, &log_file_stat);
+ if ( 0 == start_stat_result && 0 == log_stat_result )
+ {
+ int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime;
+ // only report a last run time if the last viewer was the same version
+ // because this stat will be counted against this version
+ if ( markerIsSameVersion(start_marker_file_name) )
+ {
+ gLastExecDuration = elapsed_seconds;
+ }
+ else
+ {
+ duration_log_stream << "start marker from some other version; duration is not reported";
+ gLastExecDuration = -1;
+ }
+ }
+ else
+ {
+ // at least one of the LLFile::stat calls failed, so we can't compute the run time
+ duration_log_stream << "duration stat failure; start: "<< start_stat_result << " log: " << log_stat_result;
+ gLastExecDuration = -1; // unknown
+ }
+ std::string duration_log_msg(duration_log_stream.str());
+
+ // Create a new start marker file for comparison with log file time for the next run
+ LLAPRFile start_marker_file ;
+ start_marker_file.open(start_marker_file_name, LL_APR_WB);
+ if (start_marker_file.getFileHandle())
+ {
+ recordMarkerVersion(start_marker_file);
+ start_marker_file.close();
+ }
+
+ // Rename current log file to ".old"
LLFile::rename(log_file, old_log_file);
// Set the log file to SecondLife.log
-
LLError::logToFile(log_file);
-
- // *FIX:Mani no error handling here!
- return true;
+ if (!duration_log_msg.empty())
+ {
+ LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
+ }
}
bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
@@ -2146,13 +2252,13 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
BOOST_FOREACH(const SettingsFile& file, group.files)
{
- llinfos << "Attempting to load settings for the group " << file.name()
- << " - from location " << location_key << llendl;
+ LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name()
+ << " - from location " << location_key << LL_ENDL;
LLControlGroup* settings_group = LLControlGroup::getInstance(file.name);
if(!settings_group)
{
- llwarns << "No matching settings group for name " << file.name() << llendl;
+ LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL;
continue;
}
@@ -2181,7 +2287,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))
{ // success!
- llinfos << "Loaded settings file " << full_settings_path << llendl;
+ LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL;
}
else
{ // failed to load
@@ -2195,7 +2301,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
// only complain if we actually have a filename at this point
if (!full_settings_path.empty())
{
- llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
+ LL_INFOS("Settings") << "Cannot load " << full_settings_path << " - No settings found." << LL_ENDL;
}
}
}
@@ -2230,17 +2336,24 @@ void LLAppViewer::loadColorSettings()
LLUIColorTable::instance().loadFromSettings();
}
+namespace
+{
+ void handleCommandLineError(LLControlGroupCLP& clp)
+ {
+ llwarns << "Error parsing command line options. Command Line options ignored." << llendl;
+
+ llinfos << "Command line usage:\n" << clp << llendl;
+
+ OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()),
+ LLStringUtil::null,
+ OSMB_OK);
+ }
+} // anonymous namespace
+
bool LLAppViewer::initConfiguration()
{
//Load settings files list
std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
- //LLControlGroup settings_control("SettingsFiles");
- //llinfos << "Loading settings file list " << settings_file_list << llendl;
- //if (0 == settings_control.loadFromFile(settings_file_list))
- //{
- // llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
- //}
-
LLXMLNodePtr root;
BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL);
if (!success)
@@ -2284,8 +2397,6 @@ bool LLAppViewer::initConfiguration()
gSavedSettings.setString("ClientSettingsFile",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
- gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel());
-
#ifndef LL_RELEASE_FOR_DOWNLOAD
// provide developer build only overrides for these control variables that are not
// persisted to settings.xml
@@ -2299,9 +2410,7 @@ bool LLAppViewer::initConfiguration()
{
c->setValue(true, false);
}
-#endif
-#ifndef LL_RELEASE_FOR_DOWNLOAD
gSavedSettings.setBOOL("QAMode", TRUE );
gSavedSettings.setS32("WatchdogEnabled", 0);
#endif
@@ -2337,13 +2446,7 @@ bool LLAppViewer::initConfiguration()
if(!initParseCommandLine(clp))
{
- llwarns << "Error parsing command line options. Command Line options ignored." << llendl;
-
- llinfos << "Command line usage:\n" << clp << llendl;
-
- std::ostringstream msg;
- msg << LLTrans::getString("MBCmdLineError") << clp.getErrorMessage();
- OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
+ handleCommandLineError(clp);
return false;
}
@@ -2357,8 +2460,8 @@ bool LLAppViewer::initConfiguration()
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
clp.getOption("settings")[0]);
gSavedSettings.setString("ClientSettingsFile", user_settings_filename);
- llinfos << "Using command line specified settings filename: "
- << user_settings_filename << llendl;
+ LL_INFOS("Settings") << "Using command line specified settings filename: "
+ << user_settings_filename << LL_ENDL;
}
// - load overrides from user_settings
@@ -2374,8 +2477,8 @@ bool LLAppViewer::initConfiguration()
{
std::string session_settings_filename = clp.getOption("sessionsettings")[0];
gSavedSettings.setString("SessionSettingsFile", session_settings_filename);
- llinfos << "Using session settings filename: "
- << session_settings_filename << llendl;
+ LL_INFOS("Settings") << "Using session settings filename: "
+ << session_settings_filename << LL_ENDL;
}
loadSettingsFromDirectory("Session");
@@ -2383,19 +2486,23 @@ bool LLAppViewer::initConfiguration()
{
std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];
gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename);
- llinfos << "Using user session settings filename: "
- << user_session_settings_filename << llendl;
+ LL_INFOS("Settings") << "Using user session settings filename: "
+ << user_session_settings_filename << LL_ENDL;
}
loadSettingsFromDirectory("UserSession");
// - apply command line settings
- clp.notify();
+ if (! clp.notify())
+ {
+ handleCommandLineError(clp);
+ return false;
+ }
// Register the core crash option as soon as we can
// if we want gdb post-mortem on cores we need to be up and running
// ASAP or we might miss init issue etc.
- if(clp.hasOption("disablecrashlogger"))
+ if(gSavedSettings.getBOOL("DisableCrashLogger"))
{
llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl;
LLAppViewer::instance()->disableCrashlogger();
@@ -2468,91 +2575,56 @@ bool LLAppViewer::initConfiguration()
}
}
- if(clp.hasOption("channel"))
- {
- LLVersionInfo::resetChannel(clp.getOption("channel")[0]);
- }
+ if (clp.hasOption("logevents")) {
+ LLViewerEventRecorder::instance().setEventLoggingOn();
+ }
- // If we have specified crash on startup, set the global so we'll trigger the crash at the right time
- if(clp.hasOption("crashonstartup"))
+ std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));
+ if(! CmdLineChannel.empty())
{
- gCrashOnStartup = TRUE;
+ LLVersionInfo::resetChannel(CmdLineChannel);
}
- if (clp.hasOption("logperformance"))
+ // If we have specified crash on startup, set the global so we'll trigger the crash at the right time
+ gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup");
+
+ if (gSavedSettings.getBOOL("LogPerformance"))
{
LLFastTimer::sLog = TRUE;
LLFastTimer::sLogName = std::string("performance");
}
-
- if (clp.hasOption("logmetrics"))
- {
- LLFastTimer::sMetricLog = TRUE ;
- // '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test
- // In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...)
- std::string test_name = clp.getOption("logmetrics")[0];
+
+ std::string test_name(gSavedSettings.getString("LogMetrics"));
+ if (! test_name.empty())
+ {
+ LLFastTimer::sMetricLog = TRUE ;
+ // '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test
+ // In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...)
llinfos << "'--logmetrics' argument : " << test_name << llendl;
- if (test_name == "")
- {
- llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl;
- LLFastTimer::sLogName = DEFAULT_METRIC_NAME;
- }
- else
- {
- LLFastTimer::sLogName = test_name;
- }
+ LLFastTimer::sLogName = test_name;
}
if (clp.hasOption("graphicslevel"))
{
- const LLCommandLineParser::token_vector_t& value = clp.getOption("graphicslevel");
- if(value.size() != 1)
- {
- llwarns << "Usage: -graphicslevel <0-3>" << llendl;
- }
- else
- {
- std::string detail = value.front();
- mForceGraphicsDetail = TRUE;
-
- switch (detail.c_str()[0])
- {
- case '0':
- gSavedSettings.setU32("RenderQualityPerformance", 0);
- break;
- case '1':
- gSavedSettings.setU32("RenderQualityPerformance", 1);
- break;
- case '2':
- gSavedSettings.setU32("RenderQualityPerformance", 2);
- break;
- case '3':
- gSavedSettings.setU32("RenderQualityPerformance", 3);
- break;
- default:
- mForceGraphicsDetail = FALSE;
- llwarns << "Usage: -graphicslevel <0-3>" << llendl;
- break;
- }
- }
+ // User explicitly requested --graphicslevel on the command line. We
+ // expect this switch has already set RenderQualityPerformance. Check
+ // that value for validity.
+ U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance");
+ if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel))
+ {
+ // graphicslevel is valid: save it and engage it later. Capture
+ // the requested value separately from the settings variable
+ // because, if this is the first run, LLViewerWindow's constructor
+ // will call LLFeatureManager::applyRecommendedSettings(), which
+ // overwrites this settings variable!
+ mForceGraphicsLevel = graphicslevel;
+ }
}
- if (clp.hasOption("analyzeperformance"))
- {
- LLFastTimerView::sAnalyzePerformance = TRUE;
- }
+ LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance");
+ gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession"));
- if (clp.hasOption("replaysession"))
- {
- gAgentPilot.setReplaySession(TRUE);
- }
-
- if (clp.hasOption("nonotifications"))
- {
- gSavedSettings.getControl("IgnoreAllNotifications")->setValue(true, false);
- }
-
- if (clp.hasOption("debugsession"))
+ if (gSavedSettings.getBOOL("DebugSession"))
{
gDebugSession = TRUE;
gDebugGL = TRUE;
@@ -2577,20 +2649,16 @@ bool LLAppViewer::initConfiguration()
// What can happen is that someone can use IE (or potentially
// other browsers) and do the rough equivalent of command
// injection and steal passwords. Phoenix. SL-55321
- if(clp.hasOption("url"))
- {
- LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0]));
- if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION)
- {
- LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid());
-
- }
- }
- else if(clp.hasOption("slurl"))
- {
- LLSLURL start_slurl(clp.getOption("slurl")[0]);
+ std::string CmdLineLoginLocation(gSavedSettings.getString("CmdLineLoginLocation"));
+ if(! CmdLineLoginLocation.empty())
+ {
+ LLSLURL start_slurl(CmdLineLoginLocation);
LLStartUp::setStartSLURL(start_slurl);
- }
+ if(start_slurl.getType() == LLSLURL::LOCATION)
+ {
+ LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid());
+ }
+ }
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
@@ -2631,8 +2699,6 @@ bool LLAppViewer::initConfiguration()
//}
#if LL_DARWIN
- // Initialize apple menubar and various callbacks
- init_apple_menu(LLTrans::getString("APP_NAME").c_str());
#if __ppc__
// If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further.
@@ -2696,51 +2762,34 @@ bool LLAppViewer::initConfiguration()
}
}
- if (!gSavedSettings.getBOOL("AllowMultipleViewers"))
+ //
+ // Check for another instance of the app running
+ //
+ if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers"))
{
- //
- // Check for another instance of the app running
- //
+ std::ostringstream msg;
+ msg << LLTrans::getString("MBAlreadyRunning");
+ OSMessageBox(
+ msg.str(),
+ LLStringUtil::null,
+ OSMB_OK);
+ return false;
+ }
- mSecondInstance = anotherInstanceRunning();
-
- if (mSecondInstance)
+ if (mSecondInstance)
+ {
+ // This is the second instance of SL. Turn off voice support,
+ // but make sure the setting is *not* persisted.
+ LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
+ if(disable_voice)
{
- std::ostringstream msg;
- msg << LLTrans::getString("MBAlreadyRunning");
- OSMessageBox(
- msg.str(),
- LLStringUtil::null,
- OSMB_OK);
- return false;
+ const BOOL DO_NOT_PERSIST = FALSE;
+ disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
}
-
- initMarkerFile();
-
- checkForCrash();
- }
+ }
else
{
- mSecondInstance = anotherInstanceRunning();
-
- if (mSecondInstance)
- {
- // This is the second instance of SL. Turn off voice support,
- // but make sure the setting is *not* persisted.
- LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
- if(disable_voice)
- {
- const BOOL DO_NOT_PERSIST = FALSE;
- disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
- }
- }
-
- initMarkerFile();
-
- if(!mSecondInstance)
- {
- checkForCrash();
- }
+ checkForCrash();
}
// NextLoginLocation is set from the command line option
@@ -2750,9 +2799,8 @@ bool LLAppViewer::initConfiguration()
LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
}
- else if ( ( clp.hasOption("login") || clp.hasOption("autologin"))
- && !clp.hasOption("url")
- && !clp.hasOption("slurl"))
+ else if ((clp.hasOption("login") || clp.hasOption("autologin"))
+ && gSavedSettings.getString("CmdLineLoginLocation").empty())
{
// If automatic login from command line with --login switch
// init StartSLURL location.
@@ -2769,6 +2817,16 @@ bool LLAppViewer::initConfiguration()
loadColorSettings();
+ // Let anyone else who cares know that we've populated our settings
+ // variables.
+ for (LLControlGroup::key_iter ki(LLControlGroup::beginKeys()), kend(LLControlGroup::endKeys());
+ ki != kend; ++ki)
+ {
+ // For each named instance of LLControlGroup, send an event saying
+ // we've initialized an LLControlGroup instance by that name.
+ LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", *ki));
+ }
+
return true; // Config was successful.
}
@@ -2847,25 +2905,46 @@ namespace {
std::string notification_name;
void (*apply_callback)(LLSD const &, LLSD const &) = NULL;
+ /* Build up the notification name...
+ * it can be any of these, which are included here for the sake of grep:
+ * RequiredUpdateDownloadedDialog
+ * RequiredUpdateDownloadedVerboseDialog
+ * OtherChannelRequiredUpdateDownloadedDialog
+ * OtherChannelRequiredUpdateDownloadedVerbose
+ * DownloadBackgroundTip
+ * DownloadBackgroundDialog
+ * OtherChannelDownloadBackgroundTip
+ * OtherChannelDownloadBackgroundDialog
+ */
+ {
+ LL_DEBUGS("UpdaterService") << "data = ";
+ std::ostringstream data_dump;
+ LLSDSerialize::toNotation(data, data_dump);
+ LL_CONT << data_dump.str() << LL_ENDL;
+ }
+ if(data["channel"].asString() != LLVersionInfo::getChannel())
+ {
+ notification_name.append("OtherChannel");
+ }
if(data["required"].asBoolean())
{
if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT)
{
// The user never saw the progress bar.
apply_callback = &apply_update_ok_callback;
- notification_name = "RequiredUpdateDownloadedVerboseDialog";
+ notification_name += "RequiredUpdateDownloadedVerboseDialog";
}
else if(LLStartUp::getStartupState() < STATE_WORLD_INIT)
{
// The user is logging in but blocked.
apply_callback = &apply_update_ok_callback;
- notification_name = "RequiredUpdateDownloadedDialog";
+ notification_name += "RequiredUpdateDownloadedDialog";
}
else
{
// The user is already logged in; treat like an optional update.
apply_callback = &apply_update_callback;
- notification_name = "DownloadBackgroundTip";
+ notification_name += "DownloadBackgroundTip";
}
}
else
@@ -2875,16 +2954,26 @@ namespace {
{
// CHOP-262 we need to use a different notification
// method prior to login.
- notification_name = "DownloadBackgroundDialog";
+ notification_name += "DownloadBackgroundDialog";
}
else
{
- notification_name = "DownloadBackgroundTip";
+ notification_name += "DownloadBackgroundTip";
}
}
LLSD substitutions;
substitutions["VERSION"] = data["version"];
+ std::string new_channel = data["channel"].asString();
+ substitutions["NEW_CHANNEL"] = new_channel;
+ std::string info_url = data["info_url"].asString();
+ if ( !info_url.empty() )
+ {
+ substitutions["INFO_URL"] = info_url;
+ }
+ else
+ {
+ LL_WARNS("UpdaterService") << "no info url supplied - defaulting to hard coded release notes pattern" << LL_ENDL;
// truncate version at the rightmost '.'
std::string version_short(data["version"]);
@@ -2903,7 +2992,8 @@ namespace {
relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get());
relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL"));
- substitutions["RELEASE_NOTES_FULL_URL"] = relnotes_url.getString();
+ substitutions["INFO_URL"] = relnotes_url.getString();
+ }
LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback);
}
@@ -2946,22 +3036,50 @@ namespace {
void LLAppViewer::initUpdater()
{
// Initialize the updater service.
- // Generate URL to the udpater service
// Get Channel
// Get Version
- std::string url = gSavedSettings.getString("UpdaterServiceURL");
+
+ /*****************************************************************
+ * Previously, the url was derived from the settings
+ * UpdaterServiceURL
+ * UpdaterServicePath
+ * it is now obtained from the grid manager. The settings above
+ * are no longer used.
+ *****************************************************************/
std::string channel = LLVersionInfo::getChannel();
std::string version = LLVersionInfo::getVersion();
- std::string protocol_version = gSavedSettings.getString("UpdaterServiceProtocolVersion");
- std::string service_path = gSavedSettings.getString("UpdaterServicePath");
+
U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod");
+ bool willing_to_test;
+ LL_DEBUGS("UpdaterService") << "channel " << channel << LL_ENDL;
+ static const boost::regex is_test_channel("\\bTest$");
+ if (boost::regex_search(channel, is_test_channel))
+ {
+ LL_INFOS("UpdaterService") << "Test build: overriding willing_to_test by sending testno" << LL_ENDL;
+ willing_to_test = false;
+ }
+ else
+ {
+ willing_to_test = gSavedSettings.getBOOL("UpdaterWillingToTest");
+ }
+ unsigned char unique_id[MD5HEX_STR_SIZE];
+ if ( ! llHashedUniqueID(unique_id) )
+ {
+ if ( willing_to_test )
+ {
+ LL_WARNS("UpdaterService") << "Unable to provide a unique id; overriding willing_to_test by sending testno" << LL_ENDL;
+ }
+ willing_to_test = false;
+ }
mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this));
- mUpdater->initialize(protocol_version,
- url,
- service_path,
- channel,
- version);
+ mUpdater->initialize(channel,
+ version,
+ gPlatform,
+ getOSInfo().getOSVersionString(),
+ unique_id,
+ willing_to_test
+ );
mUpdater->setCheckPeriod(check_period);
mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8));
gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()->
@@ -3060,11 +3178,12 @@ bool LLAppViewer::initWindow()
// Initialize GL stuff
//
- if (mForceGraphicsDetail)
+ if (mForceGraphicsLevel)
{
- LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false);
+ LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false);
+ gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel);
}
-
+
// Set this flag in case we crash while initializing GL
gSavedSettings.setBOOL("RenderInitError", TRUE);
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
@@ -3346,22 +3465,21 @@ void LLAppViewer::handleViewerCrash()
//we're already in a crash situation
if (gDirUtilp)
{
- std::string crash_file_name = ( gLLErrorActivated )
- ? gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LLERROR_MARKER_FILE_NAME)
- : gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME);
- LL_INFOS("MarkerFile") << "Creating crash marker file " << crash_file_name << LL_ENDL;
-
- LLAPRFile crash_file ;
- crash_file.open(crash_file_name, LL_APR_W);
- if (crash_file.getFileHandle())
+ std::string crash_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+ gLLErrorActivated
+ ? LLERROR_MARKER_FILE_NAME
+ : ERROR_MARKER_FILE_NAME);
+ LLAPRFile crash_marker_file ;
+ crash_marker_file.open(crash_marker_file_name, LL_APR_WB);
+ if (crash_marker_file.getFileHandle())
{
- LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL;
- recordMarkerVersion(crash_file);
+ LL_INFOS("MarkerFile") << "Created crash marker file " << crash_marker_file_name << LL_ENDL;
+ recordMarkerVersion(crash_marker_file);
}
else
{
- LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL;
- }
+ LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_marker_file_name << LL_ENDL;
+ }
}
else
{
@@ -3412,45 +3530,16 @@ void LLAppViewer::handleViewerCrash()
return;
}
-bool LLAppViewer::anotherInstanceRunning()
-{
- // We create a marker file when the program starts and remove the file when it finishes.
- // If the file is currently locked, that means another process is already running.
-
- std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, MARKER_FILE_NAME);
- LL_DEBUGS("MarkerFile") << "Checking marker file '"<< marker_file << "' for lock..." << LL_ENDL;
-
- //Freeze case checks
- if (LLAPRFile::isExist(marker_file, NULL, LL_APR_RB))
- {
- // File exists, try opening with write permissions
- LLAPRFile outfile ;
- outfile.open(marker_file, LL_APR_WB);
- apr_file_t* fMarker = outfile.getFileHandle() ;
- if (!fMarker)
- {
- // Another instance is running. Skip the rest of these operations.
- LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
- return true;
- }
- if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
- {
- LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
- return true;
- }
- // No other instances; we'll lock this file now & delete on quit.
- }
- LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL;
- return false;
-}
-
// static
void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file)
{
std::string marker_version(LLVersionInfo::getChannelAndVersion());
if ( marker_version.length() > MAX_MARKER_LENGTH )
{
- LL_WARNS_ONCE("MarkerFile") << "Version length ("<< marker_version.length()<< ") greater than maximum: marker matching may be incorrect" << LL_ENDL;
+ LL_WARNS_ONCE("MarkerFile") << "Version length ("<< marker_version.length()<< ")"
+ << " greater than maximum (" << MAX_MARKER_LENGTH << ")"
+ << ": marker matching may be incorrect"
+ << LL_ENDL;
}
// record the viewer version in the marker file
@@ -3470,28 +3559,23 @@ bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const
if (marker_file.getFileHandle())
{
marker_version_length = marker_file.read(marker_version, sizeof(marker_version));
- LL_DEBUGS("MarkerFile") << "Compare markers: ";
std::string marker_string(marker_version, marker_version_length);
- LL_CONT << "\n mine '" << my_version << "'"
- << "\n marker '" << marker_string << "'"
- << LL_ENDL;
if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) )
{
sameVersion = true;
}
+ LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': "
+ << "\n mine '" << my_version << "'"
+ << "\n marker '" << marker_string << "'"
+ << "\n " << ( sameVersion ? "same" : "different" ) << " version"
+ << LL_ENDL;
marker_file.close();
}
return sameVersion;
}
-void LLAppViewer::initMarkerFile()
+void LLAppViewer::processMarkerFiles()
{
- //First, check for the existence of other files.
- //There are marker files for two different types of crashes
-
- mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
- LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
-
//We've got 4 things to test for here
// - Other Process Running (SecondLife.exec_marker present, locked)
// - Freeze (SecondLife.exec_marker present, not locked)
@@ -3499,29 +3583,92 @@ void LLAppViewer::initMarkerFile()
// - Other Crash (SecondLife.error_marker present)
// These checks should also remove these files for the last 2 cases if they currently exist
- //LLError/Error checks. Only one of these should ever happen at a time.
- std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
- std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
- std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
-
- if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB) && !anotherInstanceRunning())
+ bool marker_is_same_version = true;
+ // first, look for the marker created at startup and deleted on a clean exit
+ mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
+ if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB))
{
- if ( markerIsSameVersion(mMarkerFileName) )
+ // File exists...
+ // first, read it to see if it was created by the same version (we need this later)
+ marker_is_same_version = markerIsSameVersion(mMarkerFileName);
+
+ // now test to see if this file is locked by a running process (try to open for write)
+ LL_DEBUGS("MarkerFile") << "Checking exec marker file for lock..." << LL_ENDL;
+ mMarkerFile.open(mMarkerFileName, LL_APR_WB);
+ apr_file_t* fMarker = mMarkerFile.getFileHandle() ;
+ if (!fMarker)
+ {
+ LL_INFOS("MarkerFile") << "Exec marker file open failed - assume it is locked." << LL_ENDL;
+ mSecondInstance = true; // lock means that instance is running.
+ }
+ else
+ {
+ // We were able to open it, now try to lock it ourselves...
+ if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS)
+ {
+ LL_WARNS_ONCE("MarkerFile") << "Locking exec marker failed." << LL_ENDL;
+ mSecondInstance = true; // lost a race? be conservative
+ }
+ else
+ {
+ // No other instances; we've locked this file now, so record our version; delete on quit.
+ recordMarkerVersion(mMarkerFile);
+ LL_DEBUGS("MarkerFile") << "Exec marker file existed but was not locked; rewritten." << LL_ENDL;
+ }
+ }
+
+ if (mSecondInstance)
{
- LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found" << LL_ENDL;
+ LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' owned by another instance" << LL_ENDL;
+ }
+ else if (marker_is_same_version)
+ {
+ // the file existed, is ours, and matched our version, so we can report on what it says
+ LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL;
gLastExecEvent = LAST_EXEC_FROZE;
+
}
else
{
LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found, but versions did not match" << LL_ENDL;
}
- }
+ }
+ else // marker did not exist... last exec (if any) did not freeze
+ {
+ // Create the marker file for this execution & lock it; it will be deleted on a clean exit
+ apr_status_t s;
+ s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE);
+
+ if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
+ {
+ LL_DEBUGS("MarkerFile") << "Exec marker file '"<< mMarkerFileName << "' created." << LL_ENDL;
+ if (APR_SUCCESS == apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE))
+ {
+ recordMarkerVersion(mMarkerFile);
+ LL_DEBUGS("MarkerFile") << "Exec marker file locked." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "Exec marker file cannot be locked." << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "Failed to create exec marker file '"<< mMarkerFileName << "'." << LL_ENDL;
+ }
+ }
+
+ // now check for cases in which the exec marker may have been cleaned up by crash handlers
+
+ // check for any last exec event report based on whether or not it happened during logout
+ // (the logout marker is created when logout begins)
+ std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB))
{
if (markerIsSameVersion(logout_marker_file))
{
gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
- LL_INFOS("MarkerFile") << "Logout crashed '"<< logout_marker_file << "', setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+ LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL;
}
else
{
@@ -3529,89 +3676,86 @@ void LLAppViewer::initMarkerFile()
}
LLAPRFile::remove(logout_marker_file);
}
+ // further refine based on whether or not a marker created during an llerr crash is found
+ std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB))
{
if (markerIsSameVersion(llerror_marker_file))
{
- gLastExecEvent = ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE )
- ? LAST_EXEC_LOGOUT_CRASH : LAST_EXEC_LLERROR_CRASH;
- LL_INFOS("MarkerFile") << "Last exec LLError '"<< llerror_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+ if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE )
+ {
+ gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
+ LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
+ }
+ else
+ {
+ gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
+ LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL;
+ }
}
else
{
- LL_INFOS("MarkerFile") << "Last exec LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL;
+ LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL;
}
LLAPRFile::remove(llerror_marker_file);
}
+ // and last refine based on whether or not a marker created during a non-llerr crash is found
+ std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
{
if (markerIsSameVersion(error_marker_file))
{
- gLastExecEvent = (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
- ? LAST_EXEC_LOGOUT_CRASH : LAST_EXEC_OTHER_CRASH;
- LL_INFOS("MarkerFile") << "Last exec '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+ if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE)
+ {
+ gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
+ LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL;
+ }
+ else
+ {
+ gLastExecEvent = LAST_EXEC_OTHER_CRASH;
+ LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+ }
}
else
{
- LL_INFOS("MarkerFile") << "Last exec '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
+ LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
}
LLAPRFile::remove(error_marker_file);
}
-
- // No new markers if another instance is running.
- if(anotherInstanceRunning())
- {
- return;
- }
-
- // Create the marker file for this execution & lock it
- apr_status_t s;
- s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE);
-
- if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
- {
- LL_DEBUGS("MarkerFile") << "Marker file '"<< mMarkerFileName << "' created." << LL_ENDL;
- if (APR_SUCCESS == apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE))
- {
- recordMarkerVersion(mMarkerFile);
- LL_DEBUGS("MarkerFile") << "Marker file locked." << LL_ENDL;
- }
- else
- {
- LL_INFOS("MarkerFile") << "Marker file cannot be locked." << LL_ENDL;
- }
- }
- else
- {
- LL_INFOS("MarkerFile") << "Failed to create marker file '"<< mMarkerFileName << "'." << LL_ENDL;
- }
}
void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
{
- LL_DEBUGS("MarkerFile") << "removeMarkerFile("<<leave_logout_marker<<")" << LL_ENDL;
- if (mMarkerFile.getFileHandle())
- {
- LL_DEBUGS("MarkerFile") << "removeMarkerFile marker '"<<mMarkerFileName<<"'"<< LL_ENDL;
- mMarkerFile.close();
- LLAPRFile::remove( mMarkerFileName );
- }
- else
- {
- LL_WARNS("MarkerFile") << "removeMarkerFile marker '"<<mMarkerFileName<<"' not open"<< LL_ENDL;
- }
- if (!leave_logout_marker)
- {
- if (mLogoutMarkerFile.getFileHandle())
+ if (!mSecondInstance)
+ {
+ LL_DEBUGS("MarkerFile") << (leave_logout_marker?"leave":"remove") <<" logout" << LL_ENDL;
+ if (mMarkerFile.getFileHandle())
{
- LL_DEBUGS("MarkerFile") << "removeMarkerFile marker '"<<mLogoutMarkerFileName<<"'"<< LL_ENDL;
- mLogoutMarkerFile.close();
+ LL_DEBUGS("MarkerFile") << "removing exec marker '"<<mMarkerFileName<<"'"<< LL_ENDL;
+ mMarkerFile.close() ;
+ LLAPRFile::remove( mMarkerFileName );
}
else
{
- LL_WARNS("MarkerFile") << "removeMarkerFile marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
+ LL_WARNS("MarkerFile") << "marker '"<<mMarkerFileName<<"' not open"<< LL_ENDL;
+ }
+ if (!leave_logout_marker)
+ {
+ if (mLogoutMarkerFile.getFileHandle())
+ {
+ LL_DEBUGS("MarkerFile") << "removing logout marker '"<<mLogoutMarkerFileName<<"'"<< LL_ENDL;
+ mLogoutMarkerFile.close();
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "logout marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
+ }
+ LLAPRFile::remove( mLogoutMarkerFileName );
}
- LLAPRFile::remove( mLogoutMarkerFileName );
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "leaving markers because this is a second instance" << LL_ENDL;
}
}
@@ -3659,6 +3803,18 @@ void LLAppViewer::requestQuit()
// Try to send metrics back to the grid
metricsSend(!gDisconnected);
+
+ // Try to send last batch of avatar rez metrics.
+ if (!gDisconnected && isAgentAvatarValid())
+ {
+ gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent.
+ }
+
+ // Try to send last batch of avatar rez metrics.
+ if (!gDisconnected && isAgentAvatarValid())
+ {
+ gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent.
+ }
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
effectp->setPositionGlobal(gAgent.getPositionGlobal());
@@ -4436,11 +4592,6 @@ void LLAppViewer::idle()
llinfos << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << llendl;
gObjectList.mNumDeadObjectUpdates = 0;
}
- if (gObjectList.mNumUnknownKills)
- {
- llinfos << "Kills on unknown objects: " << gObjectList.mNumUnknownKills << llendl;
- gObjectList.mNumUnknownKills = 0;
- }
if (gObjectList.mNumUnknownUpdates)
{
llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl;
@@ -4451,7 +4602,6 @@ void LLAppViewer::idle()
// The 5-second interval is nice for this purpose. If the object debug
// bit moves or is disabled, please give this a suitable home.
LLViewerAssetStatsFF::record_fps_main(gFPSClamped);
- LLViewerAssetStatsFF::record_avatar_stats();
}
}
@@ -4767,6 +4917,13 @@ void LLAppViewer::idleShutdown()
return;
}
+ if (gPendingMetricsUploads > 0
+ && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
+ && !logoutRequestSent())
+ {
+ return;
+ }
+
// All floaters are closed. Tell server we want to quit.
if( !logoutRequestSent() )
{
@@ -4792,6 +4949,22 @@ void LLAppViewer::sendLogoutRequest()
{
if(!mLogoutRequestSent && gMessageSystem)
{
+ //Set internal status variables and marker files before actually starting the logout process
+ gLogoutInProgress = TRUE;
+ mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
+
+ LLAPRFile outfile ;
+ mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB);
+ if (mLogoutMarkerFile.getFileHandle())
+ {
+ LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL;
+ recordMarkerVersion(outfile);
+ }
+ else
+ {
+ LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL;
+ }
+
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_LogoutRequest);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -4807,22 +4980,6 @@ void LLAppViewer::sendLogoutRequest()
{
LLVoiceClient::getInstance()->leaveChannel();
}
-
- //Set internal status variables and marker files
- gLogoutInProgress = TRUE;
- mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
-
- LLAPRFile outfile ;
- mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_W);
- if (mLogoutMarkerFile.getFileHandle())
- {
- LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << mLogoutMarkerFileName << LL_ENDL;
- recordMarkerVersion(outfile);
- }
- else
- {
- LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL;
- }
}
}
@@ -5071,11 +5228,12 @@ void LLAppViewer::disconnectViewer()
void LLAppViewer::forceErrorLLError()
{
- llerrs << "This is an llerror" << llendl;
+ llerrs << "This is a deliberate llerror" << llendl;
}
void LLAppViewer::forceErrorBreakpoint()
{
+ llwarns << "Forcing a deliberate breakpoint" << llendl;
#ifdef LL_WINDOWS
DebugBreak();
#endif
@@ -5084,6 +5242,7 @@ void LLAppViewer::forceErrorBreakpoint()
void LLAppViewer::forceErrorBadMemoryAccess()
{
+ llwarns << "Forcing a deliberate bad memory access" << llendl;
S32* crash = NULL;
*crash = 0xDEADBEEF;
return;
@@ -5091,6 +5250,7 @@ void LLAppViewer::forceErrorBadMemoryAccess()
void LLAppViewer::forceErrorInfiniteLoop()
{
+ llwarns << "Forcing a deliberate infinite loop" << llendl;
while(true)
{
;
@@ -5100,12 +5260,14 @@ void LLAppViewer::forceErrorInfiniteLoop()
void LLAppViewer::forceErrorSoftwareException()
{
+ llwarns << "Forcing a deliberate exception" << llendl;
// *FIX: Any way to insure it won't be handled?
throw;
}
void LLAppViewer::forceErrorDriverCrash()
{
+ llwarns << "Forcing a deliberate driver crash" << llendl;
glDeleteTextures(1, NULL);
}
@@ -5219,16 +5381,8 @@ void LLAppViewer::handleLoginComplete()
void LLAppViewer::launchUpdater()
{
LLSD query_map = LLSD::emptyMap();
- // *TODO place os string in a global constant
-#if LL_WINDOWS
- query_map["os"] = "win";
-#elif LL_DARWIN
- query_map["os"] = "mac";
-#elif LL_LINUX
- query_map["os"] = "lnx";
-#elif LL_SOLARIS
- query_map["os"] = "sol";
-#endif
+ query_map["os"] = gPlatform;
+
// *TODO change userserver to be grid on both viewer and sim, since
// userserver no longer exists.
query_map["userserver"] = LLGridManager::getInstance()->getGridId();