diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 0b651ae7e5d304d668a8e05ae00e4346876c5440..36227e67990a69c54ea09e44268ba8f78b939620 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -274,6 +274,7 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl catch (std::bad_alloc&) { // Out of memory on stack allocation? + LLError::LLUserWarningMsg::showOutOfMemory(); printActiveCoroutines(); LL_ERRS("LLCoros") << "Bad memory allocation in LLCoros::launch(" << prefix << ")!" << LL_ENDL; } diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 1b2427c633406545fd03f500c5722333e973253f..78a04163a0b2add71026905a31f4ddcdfa94017f 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -1613,6 +1613,48 @@ namespace LLError { return out << boost::stacktrace::stacktrace(); } + + // LLOutOfMemoryWarning + std::string LLUserWarningMsg::sLocalizedOutOfMemoryTitle; + std::string LLUserWarningMsg::sLocalizedOutOfMemoryWarning; + LLUserWarningMsg::Handler LLUserWarningMsg::sHandler; + + void LLUserWarningMsg::show(const std::string& message) + { + if (sHandler) + { + sHandler(std::string(), message); + } + } + + void LLUserWarningMsg::showOutOfMemory() + { + if (sHandler && !sLocalizedOutOfMemoryTitle.empty()) + { + sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning); + } + } + + void LLUserWarningMsg::showMissingFiles() + { + // Files Are missing, likely can't localize. + const std::string error_string = + "Second Life viewer couldn't access some of the files it needs and will be closed." + "\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and " + "contact https://support.secondlife.com if issue persists after reinstall."; + sHandler("Missing Files", error_string); + } + + void LLUserWarningMsg::setHandler(const LLUserWarningMsg::Handler &handler) + { + sHandler = handler; + } + + void LLUserWarningMsg::setOutOfMemoryStrings(const std::string& title, const std::string& message) + { + sLocalizedOutOfMemoryTitle = title; + sLocalizedOutOfMemoryWarning = message; + } } void crashdriver(void (*callback)(int*)) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 73433b1232dfaf378675c2aef6d2807a4e5ad398..8d9db6fddaede6b9832043a8d14acfe317459874 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -38,6 +38,7 @@ #include "llprofiler.h" #include "llpreprocessor.h" +#include <functional> // std::function const int LL_ERR_NOERR = 0; @@ -301,6 +302,28 @@ namespace LLError { friend std::ostream& operator<<(std::ostream& out, const LLStacktrace&); }; + + // Provides access to OS notification popup on error, since + // not everything has access to OS's messages + class LLUserWarningMsg + { + public: + typedef std::function<void(const std::string&, const std::string&)> Handler; + static void setHandler(const Handler&); + static void setOutOfMemoryStrings(const std::string& title, const std::string& message); + + // When viewer encounters bad alloc or can't access files try warning user about reasons + static void showOutOfMemory(); + static void showMissingFiles(); + // Genering error + static void show(const std::string&); + + private: + // needs to be preallocated before viewer runs out of memory + static std::string sLocalizedOutOfMemoryTitle; + static std::string sLocalizedOutOfMemoryWarning; + static Handler sHandler; + }; } //this is cheaper than llcallstacks if no need to output other variables to call stacks. diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp index 46560b5e4ce39ac7c12dc45b7ae1d080448090d7..0787bde57f101b02253d89cd5889dc82032ef24a 100644 --- a/indra/llcommon/llexception.cpp +++ b/indra/llcommon/llexception.cpp @@ -37,6 +37,7 @@ #include "llerror.h" #include "llerrorcontrol.h" + // used to attach and extract stacktrace information to/from boost::exception, // see https://www.boost.org/doc/libs/release/doc/html/stacktrace/getting_started.html#stacktrace.getting_started.exceptions_with_stacktrace // apparently the struct passed as the first template param needs no definition? diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index e011b1851913e4f1c111023c0e6c05d7c44bc345..0f4f409784ae71448d58feb64761ed4783b4694a 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -303,6 +303,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread) LLMemory::logMemoryInfo(TRUE); //output possible call stacks to log file. + LLError::LLUserWarningMsg::showOutOfMemory(); LLError::LLCallStacks::print(); LL_ERRS() << "Bad memory allocation in HttpService::threadRun()!" << LL_ENDL; diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp index 763f5a332860a20a58f8fed039c6932616db4d7a..7f982ccba60c7170250fca0c1b479ef2305bd69e 100644 --- a/indra/llimage/llimagebmp.cpp +++ b/indra/llimage/llimagebmp.cpp @@ -321,7 +321,8 @@ bool LLImageBMP::updateData() mColorPalette = new(std::nothrow) U8[color_palette_size]; if (!mColorPalette) { - LL_WARNS() << "Out of memory in LLImageBMP::updateData(), size: " << color_palette_size << LL_ENDL; + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Out of memory in LLImageBMP::updateData(), size: " << color_palette_size << LL_ENDL; return false; } memcpy( mColorPalette, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE + extension_size, color_palette_size ); /* Flawfinder: ignore */ diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp index f88caca5da35a4eaed4a3e13c34b493b981698d7..eab97be46eaa062c0b63641c79f77dc16a31aa7c 100644 --- a/indra/llimage/llimagedxt.cpp +++ b/indra/llimage/llimagedxt.cpp @@ -433,6 +433,7 @@ bool LLImageDXT::convertToDXR() U8* newdata = (U8*)ll_aligned_malloc_16(total_bytes); if (!newdata) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "Out of memory in LLImageDXT::convertToDXR()" << LL_ENDL; return false; } diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index 3c14fe1c0571dda95d1cb069242eab67a33b360d..7cc19d5a29679a9bbb47c89162c65ef3712caaa3 100644 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -266,6 +266,7 @@ bool LLImageTGA::updateData() mColorMap = new(std::nothrow) U8[ color_map_bytes ]; if (!mColorMap) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "Out of Memory in bool LLImageTGA::updateData()" << LL_ENDL; return false; } diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 5b764bb68dbc47f556c08fa48be38af429ff4605..835a2ed1445f533cf6effaa251750e0816fbc4c2 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1385,6 +1385,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } catch(const std::bad_alloc&) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) << " bytes for a manual image W" << width << " H" << height << LL_ENDL; } @@ -1411,6 +1412,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } catch(const std::bad_alloc&) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) << " bytes for a manual image W" << width << " H" << height << LL_ENDL; } @@ -1440,6 +1442,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt } catch(const std::bad_alloc&) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32)) << " bytes for a manual image W" << width << " H" << height << LL_ENDL; } diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 93715d8a77b3acd49fa19477842ce75df8ad1efe..d16393265abdb5eed1a5a165339856387e7de27a 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -862,7 +862,7 @@ LLRender::~LLRender() shutdown(); } -void LLRender::init(bool needs_vertex_buffer) +bool LLRender::init(bool needs_vertex_buffer) { #if GL_ARB_debug_output && !LL_DARWIN if (gGLManager.mHasDebugOutput && gDebugGL) @@ -884,10 +884,18 @@ void LLRender::init(bool needs_vertex_buffer) // necessary for reflection maps glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); +#if LL_WINDOWS + if (glGenVertexArrays == nullptr) + { + return false; + } +#endif + if (needs_vertex_buffer) { initVertexBuffer(); } + return true; } void LLRender::initVertexBuffer() diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 6d118441db5e441e5efa59c64f17d2568ce5551a..580f18a437add99b03c49ad3e2d8d00844284394 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -368,7 +368,7 @@ class LLRender LLRender(); ~LLRender(); - void init(bool needs_vertex_buffer); + bool init(bool needs_vertex_buffer); void initVertexBuffer(); void resetVertexBuffer(); void shutdown(); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 1bac017fc771b07ec6bf0f1bf81341a9103b4767..dbf6a29514b13fb223d8e5c4d4a07a1b5cdfcd55 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1556,6 +1556,7 @@ bool LLNotifications::loadTemplates() if (!success || root.isNull() || !root->hasName( "notifications" )) { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL; return false; } @@ -1566,6 +1567,7 @@ bool LLNotifications::loadTemplates() if(!params.validateBlock()) { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); LL_ERRS() << "Problem reading XUI from UI Notifications file: " << base_filename << LL_ENDL; return false; } @@ -1632,6 +1634,7 @@ bool LLNotifications::loadVisibilityRules() if(!params.validateBlock()) { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); LL_ERRS() << "Problem reading UI Notification Visibility Rules file: " << full_filename << LL_ENDL; return false; } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index bddffe2f1ba5f23171683837b99d1561be3ad99f..aef8d3119b194b8fb4f3701a98cc6bdba553b947 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2800,6 +2800,7 @@ BOOL LLTextEditor::importBuffer(const char* buffer, S32 length ) char* text = new char[ text_len + 1]; if (text == NULL) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "Memory allocation failure." << LL_ENDL; return FALSE; } diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp index 5da722a72bb8fd1815c5ee3ddcdb4cb58926f765..6c486f29ba94ebae5d824bc89a4ae79a07a5b9f9 100644 --- a/indra/llui/lltransutil.cpp +++ b/indra/llui/lltransutil.cpp @@ -44,8 +44,13 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<s bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root, LLDir::ALL_SKINS); if (!success) { + const std::string error_string = + "Second Life viewer couldn't access some of the files it needs and will be closed." + "\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and " + "contact https://support.secondlife.com if issue persists after reinstall."; + LLError::LLUserWarningMsg::show(error_string); gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN); - LL_ERRS() << "Couldn't load string table " << xml_filename << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; + LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << LL_ENDL; return false; } @@ -60,6 +65,7 @@ bool LLTransUtil::parseLanguageStrings(const std::string& xml_filename) if (!success) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Couldn't load localization table " << xml_filename << LL_ENDL; return false; } diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 0f4351266b830440a3c16f3ffcf0f4064215937b..06c65e3fc74b4f4000e853e3263bf3e029d90701 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -185,6 +185,7 @@ void LLAppCoreHttp::init() } else { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS("Init") << "Missing CA File; should be at " << ca_file << LL_ENDL; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 10375d44b677b8ee82381341d89afd53f26268a8..3d30caa7f1de56d6ec970d012759abbb8f25ea5b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -370,7 +370,6 @@ BOOL gRandomizeFramerate = FALSE; BOOL gPeriodicSlowFrame = FALSE; BOOL gCrashOnStartup = FALSE; -BOOL gLLErrorActivated = FALSE; BOOL gLogoutInProgress = FALSE; BOOL gSimulateMemLeak = FALSE; @@ -2210,9 +2209,6 @@ void errorCallback(LLError::ELevel level, const std::string &error_string) } #endif - //Set the ErrorActivated global so we know to create a marker file - gLLErrorActivated = true; - gDebugInfo["FatalMessage"] = error_string; // We're not already crashing -- we simply *intend* to crash. Since we // haven't actually trashed anything yet, we can afford to write the whole @@ -2221,6 +2217,14 @@ void errorCallback(LLError::ELevel level, const std::string &error_string) } } +void errorMSG(const std::string& title_string, const std::string& message_string) +{ + if (!message_string.empty()) + { + OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); + } +} + void LLAppViewer::initLoggingAndGetLastDuration() { // @@ -2232,6 +2236,8 @@ void LLAppViewer::initLoggingAndGetLastDuration() LLError::addGenericRecorder(&errorCallback); //LLError::setTimeFunction(getRuntime); + LLError::LLUserWarningMsg::setHandler(errorMSG); + if (mSecondInstance) { @@ -2369,6 +2375,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, { // failed to load if(file.required) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Error: Cannot load required settings file from: " << full_settings_path << LL_ENDL; return false; } @@ -2467,6 +2474,7 @@ bool LLAppViewer::initConfiguration() if (!success) { LL_WARNS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL; + LLError::LLUserWarningMsg::showMissingFiles(); if (gDirUtilp->fileExists(settings_file_list)) { LL_ERRS() << "Cannot load default configuration file settings_files.xml. " @@ -2490,6 +2498,7 @@ bool LLAppViewer::initConfiguration() if (!mSettingsLocationList->validateBlock()) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Invalid settings file list " << settings_file_list << LL_ENDL; } @@ -2952,6 +2961,8 @@ bool LLAppViewer::initConfiguration() } // [/RLVa:KB] + LLError::LLUserWarningMsg::setOutOfMemoryStrings(LLTrans::getString("MBOutOfMemoryTitle"), LLTrans::getString("MBOutOfMemoryErr")); + return true; // Config was successful. } @@ -2989,6 +3000,7 @@ void LLAppViewer::initStrings() // initial check to make sure files are there failed gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN); + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Viewer failed to find localization and UI files." << " Please reinstall viewer from https://secondlife.com/support/downloads" << " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; @@ -4179,6 +4191,7 @@ void LLAppViewer::loadKeyBindings() key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml"); if (!gViewerInput.loadBindingsXML(key_bindings_file)) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL; } } @@ -5397,6 +5410,14 @@ void LLAppViewer::forceErrorLLError() LL_ERRS() << "This is a deliberate llerror" << LL_ENDL; } +void LLAppViewer::forceErrorLLErrorMsg() +{ + LLError::LLUserWarningMsg::show("Deliberate error"); + // Note: under debug this will show a message as well, + // but release won't show anything and will quit silently + LL_ERRS() << "This is a deliberate llerror with a message" << LL_ENDL; +} + void LLAppViewer::forceErrorBreakpoint() { LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL; diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 9e52c044c36e23813d2872096edc32302400bd50..ac9bd45dbca0e687c74766885303e4b02691e509 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -152,6 +152,7 @@ class LLAppViewer : public LLApp // LLAppViewer testing helpers. // *NOTE: These will potentially crash the viewer. Only for debugging. virtual void forceErrorLLError(); + virtual void forceErrorLLErrorMsg(); virtual void forceErrorBreakpoint(); virtual void forceErrorBadMemoryAccess(); virtual void forceErrorInfiniteLoop(); diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 6f189c1b9dacaa523b4d8d9e1fb777e33b1d6868..3c5cd748e9bce14b4a84d68e9014a9977e246e1f 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -339,6 +339,7 @@ void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regio } catch (std::bad_alloc&) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "LLCoros::launch() allocation failure" << LL_ENDL; } } @@ -370,6 +371,7 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi } catch (std::bad_alloc&) { + LLError::LLUserWarningMsg::showOutOfMemory(); LL_ERRS() << "LLCoros::launch() allocation failure" << LL_ENDL; } } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 74e29fc7cfddcd9503a9dcb08ddbd6fd39ac17f3..a08fd748093c311c0a3cd8b1e95c025fcfd84adb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -308,6 +308,7 @@ void handle_disconnect_viewer(void *); void force_error_breakpoint(void *); void force_error_llerror(void *); +void force_error_llerror_msg(void*); void force_error_bad_memory_access(void *); void force_error_infinite_loop(void *); void force_error_software_exception(void *); @@ -2498,6 +2499,15 @@ class LLAdvancedForceErrorLlerror : public view_listener_t } }; +class LLAdvancedForceErrorLlerrorMsg: public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + force_error_llerror_msg(NULL); + return true; + } +}; + class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -8762,6 +8772,11 @@ void force_error_llerror(void *) LLAppViewer::instance()->forceErrorLLError(); } +void force_error_llerror_msg(void*) +{ + LLAppViewer::instance()->forceErrorLLErrorMsg(); +} + void force_error_bad_memory_access(void *) { LLAppViewer::instance()->forceErrorBadMemoryAccess(); @@ -10048,6 +10063,7 @@ void initialize_menus() // Advanced > Debugging view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint"); view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror"); + view_listener_t::addMenu(new LLAdvancedForceErrorLlerrorMsg(), "Advanced.ForceErrorLlerrorMsg"); view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess"); view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro"); view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e0f6137d69a4d42e50174b2514f09ee3b913f681..52a31e1e3b1df73491db6c26d80c5ce769a06a6c 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2230,7 +2230,11 @@ LLViewerWindow::LLViewerWindow(const Params& p) // Initialize OpenGL Renderer LLVertexBuffer::initClass(mWindow); LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; - gGL.init(true); + if (!gGL.init(true)) + { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBVideoDrvErr")); + LL_ERRS() << "gGL not initialized" << LL_ENDL; + } if (LLFeatureManager::getInstance()->isSafe() || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 708840853c5a1996cc8a1c76a1c31838073cf561..010afc40f50a1f3227167b1d8b131e0a884da969 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3220,6 +3220,12 @@ function="World.EnvPreset" <menu_item_call.on_click function="Advanced.ForceErrorLlerror" /> </menu_item_call> + <menu_item_call + label="Force LLError, Message And Crash" + name="Force LLError And Crash"> + <menu_item_call.on_click + function="Advanced.ForceErrorLlerrorMsg" /> + </menu_item_call> <menu_item_call label="Force Bad Memory Access" name="Force Bad Memory Access"> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 785ec01d1201188f52b2cedc14909c958bf306da..68bc91c248821eaf6a66ed0752781350add35c88 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3063,8 +3063,19 @@ Running in window. If you continue to receive this message, contact the [SUPPORT_SITE]. </string> + <string name="MBOutOfMemoryTitle">Out Of Memory</string> + <string name="MBOutOfMemoryErr"> + [APP_NAME]'s request for memory failed. Application can't proceed and will be closed. - <!-- Avatar Shape Information --> +If your computer's RAM is low, quit any heavy applications before runing Second Life, allocate a page file or reduce graphical settings like draw distance. + </string> + <string name="MBMissingFile"> + [APP_NAME] couldn't access or find some of the files it needs and will be closed. + +Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall. + </string> + + <!-- Avatar Shape Information --> <string name="5 O'Clock Shadow">5 O'Clock Shadow</string> <string name="All White">All White</string>