Newer
Older
.width(gSavedSettings.getU32("WindowWidth"))
.height(gSavedSettings.getU32("WindowHeight"))
.min_width(gSavedSettings.getU32("MinWindowWidth"))
.min_height(gSavedSettings.getU32("MinWindowHeight"))
.fullscreen(gSavedSettings.getBOOL("FullScreen"))
pavelkproductengine
committed
.ignore_pixel_depth(ignorePixelDepth)
.first_run(mIsFirstRun);
gViewerWindow = new LLViewerWindow(window_params);
Alexei Arabadji
committed
LL_INFOS("AppInit") << "gViewerwindow created." << LL_ENDL;
Andrew A. de Laix
committed
// Need to load feature table before cheking to start watchdog.
bool use_watchdog = false;
int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled");
Aaron Stone
committed
if (watchdog_enabled_setting == -1)
Andrew A. de Laix
committed
use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled");
}
else
{
// The user has explicitly set this setting; always use that value.
use_watchdog = bool(watchdog_enabled_setting);
}
Aaron Stone
committed
if (use_watchdog)
Andrew A. de Laix
committed
{
LLWatchdog::getInstance()->init(watchdog_killer_callback);
}
LL_INFOS("AppInit") << "watchdog setting is done." << LL_ENDL;
Andrew A. de Laix
committed
Alexei Arabadji
committed
LLNotificationsUI::LLNotificationManager::getInstance();
Igor Borovkov
committed
if (gSavedSettings.getBOOL("WindowMaximized"))
Steven Bennetts
committed
{
gViewerWindow->getWindow()->maximize();
Steven Bennetts
committed
}
//
// Initialize GL stuff
//
if (mForceGraphicsLevel)
{
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 );
LL_INFOS("AppInit") << "gPipeline Initialized" << LL_ENDL;
stop_glerror();
gViewerWindow->initGLDefaults();
gSavedSettings.setBOOL("RenderInitError", FALSE);
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
//If we have a startup crash, it's usually near GL initialization, so simulate that.
if(gCrashOnStartup)
{
LLAppViewer::instance()->forceErrorLLError();
}
//
// Determine if the window should start maximized on initial run based
// on graphics capability
//
if (gSavedSettings.getBOOL("FirstLoginThisInstall") && meetsRequirementsForMaximizedStart())
{
LL_INFOS("AppInit") << "This client met the requirements for a maximized initial screen." << LL_ENDL;
gSavedSettings.setBOOL("WindowMaximized", TRUE);
}
if (gSavedSettings.getBOOL("WindowMaximized"))
{
gViewerWindow->getWindow()->maximize();

Rye Mutt
committed
LLUI::sWindow = gViewerWindow->getWindow();
Steven Bennetts
committed
// Show watch cursor
gViewerWindow->setCursor(UI_CURSOR_WAIT);
// Finish view initialization
gViewerWindow->initBase();
// show viewer window
//gViewerWindow->getWindow()->show();
LL_INFOS("AppInit") << "Window initialization done." << LL_ENDL;
Steven Bennetts
committed
return true;
}
void LLAppViewer::writeDebugInfo(bool isStatic)
Steven Bennetts
committed
{
//Try to do the minimum when writing data during a crash.
std::string* debug_filename;
debug_filename = ( isStatic
? getStaticDebugFile()
: getDynamicDebugFile() );
LL_INFOS() << "Writing debug file " << *debug_filename << LL_ENDL;
llofstream out_file(debug_filename->c_str());
isStatic ? LLSDSerialize::toPrettyXML(gDebugInfo, out_file)
: LLSDSerialize::toPrettyXML(gDebugInfo["Dynamic"], out_file);
Steven Bennetts
committed
}
Richard Linden
committed
LLSD LLAppViewer::getViewerInfo() const
{
// The point of having one method build an LLSD info block and the other
// construct the user-visible About string is to ensure that the same info
// is available to a getInfo() caller as to the user opening
// LLFloaterAbout.
LLSD info;
auto& versionInfo(LLVersionInfo::instance());
info["VIEWER_VERSION"] = LLSDArray(versionInfo.getMajor())(versionInfo.getMinor())(versionInfo.getPatch())(versionInfo.getBuild());
info["VIEWER_VERSION_STR"] = versionInfo.getVersion();
info["CHANNEL"] = versionInfo.getChannel();
info["ADDRESS_SIZE"] = ADDRESS_SIZE;
std::string build_config = versionInfo.getBuildConfig();
if (build_config != "Release")
{
info["BUILD_CONFIG"] = build_config;
}
Richard Linden
committed
// return a URL to the release notes for this viewer, such as:
Steven Harrison (steven)
committed
// https://releasenotes.secondlife.com/viewer/2.1.0.123456.html
std::string url = versionInfo.getReleaseNotes(); // VVM supplied
if (url.empty())
{
url = LLTrans::getString("RELEASE_NOTES_BASE_URL");
if (!LLStringUtil::endsWith(url, "/"))
url += "/";
url += LLURI::escape(versionInfo.getVersion()) + ".html";
}
info["VIEWER_RELEASE_NOTES_URL"] = url;
Richard Linden
committed
// Position
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
// [RLVa:KB] - Checked: 2014-02-24 (RLVa-1.4.10)
if (RlvActions::canShowLocation())
{
// [/RLVa:KB]
LLVector3d pos = gAgent.getPositionGlobal();
info["POSITION"] = ll_sd_from_vector3d(pos);
info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos));
info["REGION"] = gAgent.getRegion()->getName();
boost::regex regex("\\.(secondlife|lindenlab)\\..*");
info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getHost().getHostName(), regex, "");
info["SERVER_VERSION"] = gLastVersionChannel;
LLSLURL slurl;
LLAgentUI::buildSLURL(slurl);
info["SLURL"] = slurl.getSLURLString();
// [RLVa:KB] - Checked: 2014-02-24 (RLVa-1.4.10)
}
else
{
Kitty Barnett
committed
info["REGION"] = RlvStrings::getString(RlvStringKeys::Hidden::Region);
Richard Linden
committed
info["SERVER_VERSION"] = gLastVersionChannel;
// [/RLVa:KB]
Richard Linden
committed
}
// CPU
info["CPU"] = gSysCPU.getCPUString();
info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().valueInUnits<LLUnits::Megabytes>());
Richard Linden
committed
// Moved hack adjustment to Windows memory size into llsys.cpp
info["OS_VERSION"] = LLOSInfo::instance().getOSString();
info["GRAPHICS_CARD_VENDOR"] = ll_safe_string((const char*)(glGetString(GL_VENDOR)));
info["GRAPHICS_CARD"] = ll_safe_string((const char*)(glGetString(GL_RENDERER)));
Richard Linden
committed
#if LL_WINDOWS
username = daianakproductengine
committed
std::string drvinfo = gDXHardware.getDriverVersionWMI();
if (!drvinfo.empty())
Richard Linden
committed
{
username = daianakproductengine
committed
info["GRAPHICS_DRIVER_VERSION"] = drvinfo;
}
else
{
LL_WARNS("DriverVersion")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL;
username = daianakproductengine
committed
LLSD driver_info = gDXHardware.getDisplayInfo();
if (driver_info.has("DriverVersion"))
{
info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
}
Richard Linden
committed
}
#endif
// [RLVa:KB] - Checked: 2010-04-18 (RLVa-1.2.0)
info["RLV_VERSION"] = (rlv_handler_t::isEnabled()) ? RlvStrings::getVersionAbout() : "(disabled)";
// [/RLVa:KB]
info["OPENGL_VERSION"] = ll_safe_string((const char*)(glGetString(GL_VERSION)));
// Settings
LLRect window_rect = gViewerWindow->getWindowRectRaw();
info["WINDOW_WIDTH"] = window_rect.getWidth();
info["WINDOW_HEIGHT"] = window_rect.getHeight();
info["FONT_SIZE_ADJUSTMENT"] = gSavedSettings.getF32("FontScreenDPI");
info["UI_SCALE"] = gSavedSettings.getF32("UIScaleFactor");
info["DRAW_DISTANCE"] = gSavedSettings.getF32("RenderFarClip");
info["NET_BANDWITH"] = gSavedSettings.getF32("ThrottleBandwidthKBPS");
info["LOD_FACTOR"] = gSavedSettings.getF32("RenderVolumeLODFactor");
info["RENDER_QUALITY"] = (F32)gSavedSettings.getU32("RenderQualityPerformance");
info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled";
info["TEXTURE_MEMORY"] = gSavedSettings.getS32("TextureMemory");
LLSD substitution;
substitution["datetime"] = (S32)(gVFS ? gVFS->creationTime() : 0);
info["VFS_TIME"] = LLTrans::getString("AboutTime", substitution);
#if LL_DARWIN
info["HIDPI"] = TRUE;
#endif
// Libraries
Richard Linden
committed
info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
bool want_fullname = true;
Mnikolenko Productengine
committed
info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : "Undefined";
Richard Linden
committed
if(LLVoiceClient::getInstance()->voiceEnabled())
{
LLVoiceVersionInfo version = LLVoiceClient::getInstance()->getVersion();
std::ostringstream version_string;
version_string << version.serverType << " " << version.serverVersion << std::endl;
info["VOICE_VERSION"] = version_string.str();
}
Richard Linden
committed
{
info["VOICE_VERSION"] = LLTrans::getString("NotConnected");
}
Rider Linden
committed
#if !LL_LINUX
std::ostringstream cef_ver_codec;
cef_ver_codec << "Dullahan: ";
cef_ver_codec << DULLAHAN_VERSION_MAJOR;
cef_ver_codec << ".";
cef_ver_codec << DULLAHAN_VERSION_MINOR;
cef_ver_codec << ".";
Callum Prentice
committed
cef_ver_codec << DULLAHAN_VERSION_POINT;
cef_ver_codec << ".";
cef_ver_codec << DULLAHAN_VERSION_BUILD;
callum_linden
committed
Callum Prentice
committed
cef_ver_codec << std::endl;
Callum Prentice
committed
cef_ver_codec << " CEF: ";
cef_ver_codec << CEF_VERSION;
callum_linden
committed
Callum Prentice
committed
cef_ver_codec << std::endl;
Callum Prentice
committed
cef_ver_codec << " Chromium: ";
cef_ver_codec << CHROME_VERSION_MAJOR;
callum_linden
committed
cef_ver_codec << ".";
cef_ver_codec << CHROME_VERSION_MINOR;
cef_ver_codec << ".";
cef_ver_codec << CHROME_VERSION_BUILD;
cef_ver_codec << ".";
cef_ver_codec << CHROME_VERSION_PATCH;
info["LIBCEF_VERSION"] = cef_ver_codec.str();
Rider Linden
committed
#else
Callum Prentice
committed
info["LIBCEF_VERSION"] = "Undefined";
callum_linden
committed
#endif
std::ostringstream vlc_ver_codec;
vlc_ver_codec << LIBVLC_VERSION_MAJOR;
vlc_ver_codec << ".";
vlc_ver_codec << LIBVLC_VERSION_MINOR;
vlc_ver_codec << ".";
vlc_ver_codec << LIBVLC_VERSION_REVISION;
info["LIBVLC_VERSION"] = vlc_ver_codec.str();
Rider Linden
committed
#else
Rider Linden
committed
#endif
Richard Linden
committed
Mnikolenko ProductEngine
committed
S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN);
if (packets_in > 0)
Richard Linden
committed
{
Mnikolenko ProductEngine
committed
info["PACKETS_LOST"] = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_LOST);
info["PACKETS_IN"] = packets_in;
Richard Linden
committed
info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal();
}
if (mServerReleaseNotesURL.empty())
{
if (gAgent.getRegion())
{
info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("RetrievingData");
}
else
{
info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("NotConnected");
}
Richard Linden
committed
}
else if (LLStringUtil::startsWith(mServerReleaseNotesURL, "http")) // it's an URL
{
info["SERVER_RELEASE_NOTES_URL"] = "[" + LLWeb::escapeURL(mServerReleaseNotesURL) + " " + LLTrans::getString("ReleaseNotes") + "]";
}
else
{
info["SERVER_RELEASE_NOTES_URL"] = mServerReleaseNotesURL;
}
return info;
}
maxim_productengine
committed
std::string LLAppViewer::getViewerInfoString(bool default_string) const
Richard Linden
committed
{
std::ostringstream support;
LLSD info(getViewerInfo());
// Render the LLSD from getInfo() as a format_map_t
LLStringUtil::format_map_t args;
// allow the "Release Notes" URL label to be localized
maxim_productengine
committed
args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes", default_string);
Richard Linden
committed
for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap());
ii != iend; ++ii)
{
if (! ii->second.isArray())
{
// Scalar value
if (ii->second.isUndefined())
{
maxim_productengine
committed
args[ii->first] = LLTrans::getString("none_text", default_string);
Richard Linden
committed
}
else
{
// don't forget to render value asString()
args[ii->first] = ii->second.asString();
}
}
else
{
// array value: build KEY_0, KEY_1 etc. entries
for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n)
{
args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString();
}
}
}
// Now build the various pieces
maxim_productengine
committed
support << LLTrans::getString("AboutHeader", args, default_string);
if (info.has("BUILD_CONFIG"))
{
maxim_productengine
committed
support << "\n" << LLTrans::getString("BuildConfig", args, default_string);
Richard Linden
committed
if (info.has("REGION"))
{
// [RLVa:KB] - Checked: 2014-02-24 (RLVa-1.4.10)
support << "\n\n" << LLTrans::getString( (RlvActions::canShowLocation()) ? "AboutPosition" : "AboutPositionRLVShowLoc", args, default_string);
// [/RLVa:KB]
// support << "\n\n" << LLTrans::getString("AboutPosition", args);
Richard Linden
committed
}
maxim_productengine
committed
support << "\n\n" << LLTrans::getString("AboutSystem", args, default_string);
Richard Linden
committed
support << "\n";
if (info.has("GRAPHICS_DRIVER_VERSION"))
{
maxim_productengine
committed
support << "\n" << LLTrans::getString("AboutDriver", args, default_string);
Richard Linden
committed
}
maxim_productengine
committed
support << "\n" << LLTrans::getString("AboutOGL", args, default_string);
support << "\n\n" << LLTrans::getString("AboutSettings", args, default_string);
maxim_productengine
committed
support << "\n\n" << LLTrans::getString("AboutLibs", args, default_string);
Richard Linden
committed
if (info.has("COMPILER"))
{
maxim_productengine
committed
support << "\n" << LLTrans::getString("AboutCompiler", args, default_string);
Richard Linden
committed
}
if (info.has("PACKETS_IN"))
{
maxim_productengine
committed
support << '\n' << LLTrans::getString("AboutTraffic", args, default_string);
Richard Linden
committed
}
// SLT timestamp
LLSD substitution;
substitution["datetime"] = (S32)time(NULL);//(S32)time_corrected();
maxim_productengine
committed
support << "\n" << LLTrans::getString("AboutTime", substitution, default_string);
Mnikolenko Productengine
committed
return support.str();
}
Steven Bennetts
committed
void LLAppViewer::cleanupSavedSettings()
{
gSavedSettings.setBOOL("MouseSun", FALSE);
gSavedSettings.setBOOL("UseEnergy", TRUE); // force toggle to turn off, since sends message to simulator
gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
Steven Bennetts
committed
gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
Steven Bennetts
committed
{
gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
Steven Bennetts
committed
}
// save window position if not maximized
Steven Bennetts
committed
// as we don't track it in callbacks
Mark Palange (Mani)
committed
if(NULL != gViewerWindow)
Steven Bennetts
committed
{
BOOL maximized = gViewerWindow->getWindow()->getMaximized();
Mark Palange (Mani)
committed
if (!maximized)
Steven Bennetts
committed
{
Mark Palange (Mani)
committed
LLCoordScreen window_pos;
if (gViewerWindow->getWindow()->getPosition(&window_pos))
Mark Palange (Mani)
committed
{
gSavedSettings.setS32("WindowX", window_pos.mX);
gSavedSettings.setS32("WindowY", window_pos.mY);
}
Steven Bennetts
committed
}
}
gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale );
Steven Bennetts
committed
// Some things are cached in LLAgent.
if (gAgent.isInitialized())
Steven Bennetts
committed
{
gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance);
Steven Bennetts
committed
}
}
void LLAppViewer::removeCacheFiles(const std::string& file_mask)
Steven Bennetts
committed
{
Vadim ProductEngine
committed
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask);
Steven Bennetts
committed
}
void LLAppViewer::writeSystemInfo()
{
if (! gDebugInfo.has("Dynamic") )
gDebugInfo["Dynamic"] = LLSD::emptyMap();
gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"Alchemy.log");
#else
//Not ideal but sufficient for good reporting.
gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"Alchemy.old"); //LLError::logFileName();
Kyle Machulis
committed
gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel();
gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor();
gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor();
gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch();
gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::instance().getBuild();
gDebugInfo["ClientInfo"]["AddressSize"] = LLVersionInfo::instance().getAddressSize();
Kyle Machulis
committed
gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString();
Kyle Machulis
committed
gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily();
Tofu Linden
committed
gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz();
Kyle Machulis
committed
gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec();
gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB().value());
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>());
gDebugInfo["OSInfo"] = LLOSInfo::instance().getOSStringSimple();
// The user is not logged on yet, but record the current grid choice login url
// which may have been the intended grid.
gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId();
#ifdef LL_WINDOWS
DWORD thread_id = GetCurrentThreadId();
gDebugInfo["MainloopThreadID"] = (S32)thread_id;
#endif
Steven Bennetts
committed
// "CrashNotHandled" is set here, while things are running well,
// in case of a freeze. If there is a freeze, the crash logger will be launched
// and can read this value from the debug_info.log.
// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
// then the value of "CrashNotHandled" will be set to true.
gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
Andrew A. de Laix
committed
// Insert crash host url (url to post crash log to) if configured. This insures
// that the crash report will go to the proper location in the case of a
Andrew A. de Laix
committed
// prior freeze.
std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
if(crashHostUrl != "")
{
gDebugInfo["CrashHostUrl"] = crashHostUrl;
}
Steven Bennetts
committed
// Dump some debugging info
LL_INFOS("SystemInfo") << "Application: " << LLTrans::getString("APP_NAME") << LL_ENDL;
LL_INFOS("SystemInfo") << "Version: " << LLVersionInfo::instance().getChannelAndVersion() << LL_ENDL;
Steven Bennetts
committed
// Dump the local time and time zone
time_t now;
time(&now);
char tbuffer[256]; /* Flawfinder: ignore */
strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now));
LL_INFOS("SystemInfo") << "Local time: " << tbuffer << LL_ENDL;
Steven Bennetts
committed
// query some system information
LL_INFOS("SystemInfo") << "CPU info:\n" << gSysCPU << LL_ENDL;
LL_INFOS("SystemInfo") << "Memory info:\n" << gSysMemory << LL_ENDL;
LL_INFOS("SystemInfo") << "OS: " << LLOSInfo::instance().getOSStringSimple() << LL_ENDL;
LL_INFOS("SystemInfo") << "OS info: " << LLOSInfo::instance() << LL_ENDL;
gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
writeDebugInfo(); // Save out debug_info.log early, in case of crash.
Steven Bennetts
committed
}
//For whatever reason, in Windows when using OOP server for breakpad, the callback to get the
//name of the dump file is not getting triggered by the breakpad library. Unfortunately they
//also didn't see fit to provide a simple query request across the pipe to get this name either.
//Since we are putting our output in a runtime generated directory and we know the header data in
//the dump format, we can however use the following hack to identify our file.
void getFileList()
{
std::stringstream filenames;
typedef std::vector<std::string> vec;
std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"");
vec file_vec = gDirUtilp->getFilesInDir(pathname);
for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter)
{
filenames << *iter << " ";
if ( ( iter->length() > 30 ) && (iter->rfind(".dmp") == (iter->length()-4) ) )
{
std::string fullname = pathname + *iter;
andreykproductengine
committed
llifstream fdat( fullname.c_str(), std::ifstream::binary);
if (fdat)
{
char buf[5];
fdat.read(buf,4);
fdat.close();
if (!strncmp(buf,"MDMP",4))
{
gDebugInfo["Dynamic"]["MinidumpPath"] = fullname;
}
}
}
}
filenames << std::endl;
gDebugInfo["Dynamic"]["DumpDirContents"] = filenames.str();
}
#endif
Steven Bennetts
committed
void LLAppViewer::handleViewerCrash()
{
LL_INFOS("CRASHREPORT") << "Handle viewer crash entry." << LL_ENDL;
LL_INFOS("CRASHREPORT") << "Last render pool type: " << LLPipeline::sCurRenderPoolType << LL_ENDL ;
Xiaohong Bao
committed
LLMemory::logMemoryInfo(true) ;
//print out recorded call stacks if there are any.
Steven Bennetts
committed
LLAppViewer* pApp = LLAppViewer::instance();
if (pApp->beingDebugged())
{
// This will drop us into the debugger.
abort();
}
Vadim ProductEngine
committed
if (LLApp::isCrashloggerDisabled())
{
abort();
}
Steven Bennetts
committed
// Returns whether a dialog was shown.
// Only do the logic in here once
if (pApp->mReportedCrash)
{
return;
}
pApp->mReportedCrash = TRUE;
Andrew A. de Laix
committed
// Insert crash host url (url to post crash log to) if configured.
std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
if(crashHostUrl != "")
{
gDebugInfo["Dynamic"]["CrashHostUrl"] = crashHostUrl;
Andrew A. de Laix
committed
}
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if ( parcel && parcel->getMusicURL()[0])
{
gDebugInfo["Dynamic"]["ParcelMusicURL"] = parcel->getMusicURL();
if ( parcel && parcel->getMediaURL()[0])
{
gDebugInfo["Dynamic"]["ParcelMediaURL"] = parcel->getMediaURL();
gDebugInfo["Dynamic"]["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
gDebugInfo["Dynamic"]["RAMInfo"]["Allocated"] = LLSD::Integer(LLMemory::getCurrentRSS() / 1024);
if(gLogoutInProgress)
{
gDebugInfo["Dynamic"]["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
}
else
{
gDebugInfo["Dynamic"]["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH;
}
if(gAgent.getRegion())
{
gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
gDebugInfo["Dynamic"]["CurrentRegion"] = gAgent.getRegion()->getName();
const LLVector3& loc = gAgent.getPositionAgent();
gDebugInfo["Dynamic"]["CurrentLocationX"] = loc.mV[0];
gDebugInfo["Dynamic"]["CurrentLocationY"] = loc.mV[1];
gDebugInfo["Dynamic"]["CurrentLocationZ"] = loc.mV[2];
Steven Bennetts
committed
if(LLAppViewer::instance()->mMainloopTimeout)
{
gDebugInfo["Dynamic"]["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
// The crash is being handled here so set this value to false.
// Otherwise the crash logger will think this crash was a freeze.
gDebugInfo["Dynamic"]["CrashNotHandled"] = (LLSD::Boolean)false;
//Write out the crash status file
//Use marker file style setup, as that's the simplest, especially since
//we're already in a crash situation
if (gDirUtilp)
{
Oz Linden
committed
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())
Oz Linden
committed
LL_INFOS("MarkerFile") << "Created crash marker file " << crash_marker_file_name << LL_ENDL;
recordMarkerVersion(crash_marker_file);
}
else
{
Oz Linden
committed
LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_marker_file_name << LL_ENDL;
}
else
{
LL_WARNS("MarkerFile") << "No gDirUtilp with which to create error marker file name" << LL_ENDL;
#ifdef LL_WINDOWS
gDebugInfo["Dynamic"]["CrashType"]="crash";
Steven Bennetts
committed
if (gMessageSystem && gDirUtilp)
{
std::string filename;
filename = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "stats.log");
LL_DEBUGS("CRASHREPORT") << "recording stats " << filename << LL_ENDL;
Oz Linden
committed
llofstream file(filename.c_str(), std::ios_base::binary);
Steven Bennetts
committed
if(file.good())
{
gMessageSystem->summarizeLogs(file);
Kyle Machulis
committed
file.close();
Steven Bennetts
committed
}
else
{
LL_WARNS("CRASHREPORT") << "problem recording stats" << LL_ENDL;
Steven Bennetts
committed
}
if (gMessageSystem)
{
Kyle Machulis
committed
gMessageSystem->getCircuitInfo(gDebugInfo["CircuitInfo"]);
Steven Bennetts
committed
gMessageSystem->stopLogging();
}
if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]);
Steven Bennetts
committed
// Close the debug file
pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead.
Steven Bennetts
committed
}
// static
void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file)
{
std::string marker_version(LLVersionInfo::instance().getChannelAndVersion());
if ( marker_version.length() > MAX_MARKER_LENGTH )
{
Oz Linden
committed
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
marker_file.write(marker_version.data(), marker_version.length());
}
bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const
{
bool sameVersion = false;
std::string my_version(LLVersionInfo::instance().getChannelAndVersion());
char marker_version[MAX_MARKER_LENGTH];
S32 marker_version_length;
LLAPRFile marker_file;
marker_file.open(marker_name, LL_APR_RB);
if (marker_file.getFileHandle())
{
marker_version_length = marker_file.read(marker_version, sizeof(marker_version));
std::string marker_string(marker_version, marker_version_length);
if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) )
{
sameVersion = true;
}
Oz Linden
committed
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;
}
Oz Linden
committed
void LLAppViewer::processMarkerFiles()
Steven Bennetts
committed
{
//We've got 4 things to test for here
// - Other Process Running (SecondLife.exec_marker present, locked)
// - Freeze (SecondLife.exec_marker present, not locked)
// - LLError Crash (SecondLife.llerror_marker present)
// - Other Crash (SecondLife.error_marker present)
// These checks should also remove these files for the last 2 cases if they currently exist
Oz Linden
committed
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))
Oz Linden
committed
// 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() ;
Oz Linden
committed
if (!fMarker)
{
Oz Linden
committed
LL_INFOS("MarkerFile") << "Exec marker file open failed - assume it is locked." << LL_ENDL;
mSecondInstance = true; // lock means that instance is running.
}
else
{
Oz Linden
committed
// 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.
Oz Linden
committed
recordMarkerVersion(mMarkerFile);
LL_DEBUGS("MarkerFile") << "Exec marker file existed but was not locked; rewritten." << LL_ENDL;
}
}
if (mSecondInstance)
{
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;
}
Oz Linden
committed
}
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);
Oz Linden
committed
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))
Oz Linden
committed
{
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;
Oz Linden
committed
LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL;
}
else
{
LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "' found, but versions did not match" << LL_ENDL;
}
LLAPRFile::remove(logout_marker_file);
Oz Linden
committed
// 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))
{
Oz Linden
committed
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
{
Oz Linden
committed
LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL;
}
LLAPRFile::remove(llerror_marker_file);
Oz Linden
committed
// 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))
Oz Linden
committed
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;
Oz Linden
committed
}
else
{
Oz Linden
committed
LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
}
LLAPRFile::remove(error_marker_file);
Steven Bennetts
committed
}
Steven Bennetts
committed
{
Oz Linden
committed
if (!mSecondInstance)
Oz Linden
committed
if (mMarkerFile.getFileHandle())
{
Oz Linden
committed
mMarkerFile.close() ;
LLAPRFile::remove( mMarkerFileName );
LL_DEBUGS("MarkerFile") << "removed exec marker '"<<mMarkerFileName<<"'"<< LL_ENDL;
}
else
{
Oz Linden
committed
LL_WARNS("MarkerFile") << "marker '"<<mMarkerFileName<<"' not open"<< LL_ENDL;
if (mLogoutMarkerFile.getFileHandle())
Oz Linden
committed
{
mLogoutMarkerFile.close();
Oz Linden
committed
LLAPRFile::remove( mLogoutMarkerFileName );
LL_DEBUGS("MarkerFile") << "removed logout marker '"<<mLogoutMarkerFileName<<"'"<< LL_ENDL;
}
else
{
LL_WARNS("MarkerFile") << "logout marker '"<<mLogoutMarkerFileName<<"' not open"<< LL_ENDL;
}
Oz Linden
committed
}
else
{
LL_WARNS("MarkerFile") << "leaving markers because this is a second instance" << LL_ENDL;
Steven Bennetts
committed
}
void LLAppViewer::removeDumpDir()
{
//Call this routine only on clean exit. Crash reporter will clean up
//its locking table for us.
std::string dump_dir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
gDirUtilp->deleteDirAndContents(dump_dir);
}
Steven Bennetts
committed
void LLAppViewer::forceQuit()
{
LLApp::setQuitting();
Steven Bennetts
committed
}
void LLAppViewer::fastQuit(S32 error_code)
// finish pending transfers
flushVFSIO();
// let sim know we're logging out
sendLogoutRequest();
// flush network buffers by shutting down messaging system
end_messaging_system();
// figure out the error code
S32 final_error_code = error_code ? error_code : (S32)isError();
// this isn't a crash
// get outta here
_exit(final_error_code);
}
Steven Bennetts
committed
void LLAppViewer::requestQuit()
{
Steven Bennetts
committed
LLViewerRegion* region = gAgent.getRegion();
Steven Bennetts
committed
if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
{
// If we have a region, make some attempt to send a logout request first.
// This prevents the halfway-logged-in avatar from hanging around inworld for a couple minutes.
if(region)
{
sendLogoutRequest();
}
Steven Bennetts
committed
// Quit immediately
forceQuit();
return;
}
Monty Brandenberg
committed
// 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.
}
if (!gSavedSettings.getBOOL("AlchemyDisableEffectSpiral"))
{
LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
effectp->setPositionGlobal(gAgent.getPositionGlobal());
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
LLHUDManager::getInstance()->sendEffects();
effectp->markDead();//remove it.
}
Steven Bennetts
committed
// Attempt to close all floaters that might be
// editing things.