diff options
24 files changed, 189 insertions, 19 deletions
| diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 70a3747b71..df49f5fa42 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -24,6 +24,8 @@ jobs:      outputs:        viewer_channel: ${{ steps.build.outputs.viewer_channel }}        viewer_version: ${{ steps.build.outputs.viewer_version }} +      viewer_branch:  ${{ steps.which-branch.outputs.branch }} +      relnotes:       ${{ steps.which-branch.outputs.relnotes }}        imagename: ${{ steps.build.outputs.imagename }}      env:        AUTOBUILD_ADDRSIZE: 64 @@ -334,7 +336,7 @@ jobs:            version: ${{ needs.build.outputs.viewer_version }}    release: -    needs: [sign-and-package-windows, sign-and-package-mac] +    needs: [build, sign-and-package-windows, sign-and-package-mac]      runs-on: ubuntu-latest      if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life_')      steps: @@ -365,17 +367,31 @@ jobs:            mv newview/viewer_version.txt macOS-viewer_version.txt        # forked from softprops/action-gh-release -      - uses: secondlife-3p/action-gh-release@v1 +      - name: Create GitHub release +        id: release +        uses: secondlife-3p/action-gh-release@v1          with: -          # name the release page for the build number so we can find it -          # easily (analogous to looking up a codeticket build page) -          name: "v${{ github.run_id }}" +          # name the release page for the branch +          name: "${{ needs.build.outputs.viewer_branch }}" +          # SL-20546: want the channel and version to be visible on the +          # release page +          body: | +            Build ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} +            ${{ needs.build.outputs.viewer_channel }} +            ${{ needs.build.outputs.viewer_version }} +            ${{ needs.build.outputs.relnotes }}            prerelease: true            generate_release_notes: true -          # the only reason we generate a GH release is to post build products +          target_commitish: ${{ github.sha }} +          previous_tag: release +          append_body: true            fail_on_unmatched_files: true            files: |              *.dmg               *.exe              *-autobuild-package.xml              *-viewer_version.txt + +      - name: post release URL +        run: | +          echo "::notice::Release ${{ steps.release.outputs.url }}" diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 3ab97b557f..1d383f174d 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -278,6 +278,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 414515854a..3de641fcba 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -1601,6 +1601,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 05dd88ee51..6f6b349cf5 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -39,6 +39,7 @@  #include "llpreprocessor.h"  #include <boost/static_assert.hpp> +#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 46560b5e4c..0787bde57f 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 294acd7f63..517076804d 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -320,6 +320,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 90b7272efa..cdea0da68d 100644 --- a/indra/llimage/llimagebmp.cpp +++ b/indra/llimage/llimagebmp.cpp @@ -321,6 +321,7 @@ bool LLImageBMP::updateData()  		mColorPalette = new(std::nothrow) U8[color_palette_size];  		if (!mColorPalette)  		{ +            LLError::LLUserWarningMsg::showOutOfMemory();  			LL_ERRS() << "Out of memory in LLImageBMP::updateData()" << LL_ENDL;  			return false;  		} diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp index 36317a5ba8..ae76c5243f 100644 --- a/indra/llimage/llimagedxt.cpp +++ b/indra/llimage/llimagedxt.cpp @@ -437,6 +437,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 88bdae9b80..152a7f309c 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 c6fd824c4e..56a12b07b1 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1353,6 +1353,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt                  scratch = new(std::nothrow) U32[width * height];                  if (!scratch)                  { +                    LLError::LLUserWarningMsg::showOutOfMemory();                      LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))                                << " bytes for a manual image W" << width << " H" << height << LL_ENDL;                  } @@ -1378,6 +1379,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt                  scratch = new(std::nothrow) U32[width * height];                  if (!scratch)                  { +                    LLError::LLUserWarningMsg::showOutOfMemory();                      LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))                          << " bytes for a manual image W" << width << " H" << height << LL_ENDL;                  } @@ -1406,6 +1408,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt                  scratch = new(std::nothrow) U32[width * height];                  if (!scratch)                  { +                    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 ee66122774..4d64dc9e10 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -857,7 +857,7 @@ LLRender::~LLRender()  	shutdown();  } -void LLRender::init(bool needs_vertex_buffer) +bool LLRender::init(bool needs_vertex_buffer)  {  #if LL_WINDOWS      if (gGLManager.mHasDebugOutput && gDebugGL) @@ -879,6 +879,13 @@ 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 +      { //bind a dummy vertex array object so we're core profile compliant          U32 ret;          glGenVertexArrays(1, &ret); @@ -889,6 +896,7 @@ void LLRender::init(bool needs_vertex_buffer)      {          initVertexBuffer();      } +    return true;  }  void LLRender::initVertexBuffer() diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index fd922affba..716b52354d 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -375,7 +375,7 @@ public:  	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 d736aa6634..2fe9ee18e3 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1553,6 +1553,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;  	} @@ -1563,6 +1564,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;  	} @@ -1629,6 +1631,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 092739a538..a247e8700a 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2694,6 +2694,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 5da722a72b..6c486f29ba 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 debf93dccd..51e259992d 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -168,6 +168,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 28dd2a3c9a..eb62fe0c18 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -363,7 +363,6 @@ BOOL gRandomizeFramerate = FALSE;  BOOL gPeriodicSlowFrame = FALSE;  BOOL gCrashOnStartup = FALSE; -BOOL gLLErrorActivated = FALSE;  BOOL gLogoutInProgress = FALSE;  BOOL gSimulateMemLeak = FALSE; @@ -2254,9 +2253,6 @@ void errorCallback(LLError::ELevel level, const std::string &error_string)          OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);  #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 @@ -2265,6 +2261,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()  {      // @@ -2276,6 +2280,8 @@ void LLAppViewer::initLoggingAndGetLastDuration()      LLError::addGenericRecorder(&errorCallback);      //LLError::setTimeFunction(getRuntime); +    LLError::LLUserWarningMsg::setHandler(errorMSG); +      if (mSecondInstance)      { @@ -2413,6 +2419,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;  				} @@ -2511,6 +2518,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. " @@ -2534,6 +2542,7 @@ bool LLAppViewer::initConfiguration()  	if (!mSettingsLocationList->validateBlock())  	{ +        LLError::LLUserWarningMsg::showMissingFiles();          LL_ERRS() << "Invalid settings file list " << settings_file_list << LL_ENDL;  	} @@ -2968,6 +2977,8 @@ bool LLAppViewer::initConfiguration()  		LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", key));  	} +    LLError::LLUserWarningMsg::setOutOfMemoryStrings(LLTrans::getString("MBOutOfMemoryTitle"), LLTrans::getString("MBOutOfMemoryErr")); +  	return true; // Config was successful.  } @@ -3005,6 +3016,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; @@ -4310,6 +4322,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;  		}  	} @@ -5400,6 +5413,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 6d1496d517..77a1cdb485 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -152,6 +152,7 @@ public:      // 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 a6c9a41fa4..b95b971890 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/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 01d6469010..6dc4f25d02 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1360,7 +1360,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)  				U8* buffer = new(std::nothrow) U8[size];  				if (!buffer)  				{ -					LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL; +					LL_WARNS(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL;  					return false;  				}  				LLMeshRepository::sCacheBytesRead += size; @@ -1473,7 +1473,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  				U8* buffer = new(std::nothrow) U8[size];  				if (!buffer)  				{ -					LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL; +					LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;  					return false;  				}  				LLMeshRepository::sCacheBytesRead += size; @@ -1575,7 +1575,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  				U8* buffer = new(std::nothrow) U8[size];  				if (!buffer)  				{ -					LL_WARNS_ONCE(LOG_MESH) << "Failed to allocate memory for physics shape, size: " << size << LL_ENDL; +					LL_WARNS(LOG_MESH) << "Failed to allocate memory for physics shape, size: " << size << LL_ENDL;  					return false;  				}  				file.read(buffer, size); @@ -1770,7 +1770,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,  				U8* buffer = new(std::nothrow) U8[size];  				if (!buffer)  				{ -					LL_WARNS_ONCE(LOG_MESH) << "Can't allocate memory for mesh " << mesh_id << " LOD " << lod << ", size: " << size << LL_ENDL; +					LL_WARNS(LOG_MESH) << "Can't allocate memory for mesh " << mesh_id << " LOD " << lod << ", size: " << size << LL_ENDL;  					// todo: for now it will result in indefinite constant retries, should result in timeout  					// or in retry-count and disabling mesh. (but usually viewer is beyond saving at this point)  					return false; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 972aac0baf..d5e4de03a9 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -289,6 +289,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 *); @@ -2414,6 +2415,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) @@ -8393,6 +8403,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(); @@ -9619,6 +9634,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 58024fb60e..1459686f10 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1957,7 +1957,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 1d012cd348..4719b091ab 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2717,6 +2717,12 @@ function="World.EnvPreset"                   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">                  <menu_item_call.on_click diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f3b26820d2..7360c06f86 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3019,8 +3019,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> | 
