summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llappviewer.cpp35
-rw-r--r--indra/newview/llappviewer.h7
-rw-r--r--indra/newview/llmeshrepository.cpp70
3 files changed, 67 insertions, 45 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b380b09129..d25762f561 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -646,6 +646,7 @@ LLAppViewer::LLAppViewer()
mSavedFinalSnapshot(false),
mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded.
mQuitRequested(false),
+ mClosingFloaters(false),
mLogoutRequestSent(false),
mLastAgentControlFlags(0),
mLastAgentForceUpdate(0),
@@ -4028,6 +4029,7 @@ void LLAppViewer::requestQuit()
{
// application is quitting
gFloaterView->closeAllChildren(true);
+ mClosingFloaters = true;
}
// Send preferences once, when exiting
@@ -4091,6 +4093,7 @@ void LLAppViewer::abortQuit()
{
LL_INFOS() << "abortQuit()" << LL_ENDL;
mQuitRequested = false;
+ mClosingFloaters = false;
}
void LLAppViewer::migrateCacheDirectory()
@@ -5040,10 +5043,19 @@ void LLAppViewer::idleShutdown()
}
// Wait for all floaters to get resolved
- if (gFloaterView
- && !gFloaterView->allChildrenClosed())
+ if (gFloaterView)
{
- return;
+ if (!mClosingFloaters)
+ {
+ // application is quitting
+ gFloaterView->closeAllChildren(true);
+ mClosingFloaters = true;
+ return;
+ }
+ if (!gFloaterView->allChildrenClosed())
+ {
+ return;
+ }
}
// ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()
@@ -5204,6 +5216,23 @@ void LLAppViewer::postToMainCoro(const LL::WorkQueue::Work& work)
gMainloopWork.post(work);
}
+void LLAppViewer::outOfMemorySoftQuit()
+{
+ if (!mQuitRequested)
+ {
+ // Todo:
+ // Find a way to free at least some memory to make it safer
+ // Pause decoding and mesh repositorie
+ getTextureCache()->pause();
+ getTextureFetch()->pause();
+ LLLFSThread::sLocal->pause();
+ gLogoutTimer.reset();
+ mQuitRequested = true;
+
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ }
+}
+
void LLAppViewer::idleNameCache()
{
// Neither old nor new name cache can function before agent has a region
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 417ab0fa00..cf5f1ab1e3 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -230,6 +230,12 @@ public:
// post given work to the "mainloop" work queue for handling on the main thread
void postToMainCoro(const LL::WorkQueue::Work& work);
+ // Attempt a 'soft' quit with disconnect and saving of settings/cache.
+ // Intended to be thread safe.
+ // Good chance of viewer crashing either way, but better than alternatives.
+ // Note: mQuitRequested can be aborted by user.
+ void outOfMemorySoftQuit();
+
protected:
virtual bool initWindow(); // Initialize the viewer's window.
virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system
@@ -317,6 +323,7 @@ private:
boost::optional<U32> mForceGraphicsLevel;
bool mQuitRequested; // User wants to quit, may have modified documents open.
+ bool mClosingFloaters;
bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim.
U32 mLastAgentControlFlags;
F32 mLastAgentForceUpdate;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a1b2d502af..4c5cc37766 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1360,20 +1360,18 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
U8* buffer = new(std::nothrow) U8[size];
if (!buffer)
{
+ LL_WARNS(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL;
+
// Not sure what size is reasonable for skin info,
// but if 20MB allocation failed, we definetely have issues
- const S32 MAX_SIZE = 20 * 1024 * 1024; //20MB
+ const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
if (size < MAX_SIZE)
{
- LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS() << "Bad memory allocation for skin info, size: " << size << LL_ENDL;
- }
- else
- {
- // Ignore failures for anomalously large data
- LL_WARNS(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL;
- }
- return false;
+ LLAppViewer::instance()->outOfMemorySoftQuit();
+ } // else ignore failures for anomalously large data
+ LLMutexLock locker(mMutex);
+ mSkinUnavailableQ.emplace_back(mesh_id);
+ return true;
}
LLMeshRepository::sCacheBytesRead += size;
++LLMeshRepository::sCacheReads;
@@ -1485,20 +1483,16 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
U8* buffer = new(std::nothrow) U8[size];
if (!buffer)
{
+ LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
+
// Not sure what size is reasonable for decomposition
// but if 20MB allocation failed, we definetely have issues
- const S32 MAX_SIZE = 20 * 1024 * 1024; //20MB
+ const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
if (size < MAX_SIZE)
{
- LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS() << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
- }
- else
- {
- // Ignore failures for anomalously large decompositiions
- LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
- }
- return false;
+ LLAppViewer::instance()->outOfMemorySoftQuit();
+ } // else ignore failures for anomalously large decompositiions
+ return true;
}
LLMeshRepository::sCacheBytesRead += size;
++LLMeshRepository::sCacheReads;
@@ -1599,20 +1593,16 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
U8* buffer = new(std::nothrow) U8[size];
if (!buffer)
{
+ LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
+
// Not sure what size is reasonable for physcis
// but if 20MB allocation failed, we definetely have issues
- const S32 MAX_SIZE = 20 * 1024 * 1024; //20MB
+ const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
if (size < MAX_SIZE)
{
- LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS() << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
- }
- else
- {
- // Ignore failures for anomalously large meshes
- LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
- }
- return false;
+ LLAppViewer::instance()->outOfMemorySoftQuit();
+ } // else ignore failures for anomalously large data
+ return true;
}
file.read(buffer, size);
@@ -1802,22 +1792,18 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
U8* buffer = new(std::nothrow) U8[size];
if (!buffer)
{
+ LL_WARNS(LOG_MESH) << "Can't allocate memory for mesh " << mesh_id << " LOD " << lod << ", size: " << size << LL_ENDL;
+
// Not sure what size is reasonable for a mesh,
// but if 20MB allocation failed, we definetely have issues
- const S32 MAX_SIZE = 20 * 1024 * 1024; //20MB
+ const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
if (size < MAX_SIZE)
{
- LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS() << "Can't allocate memory for mesh " << mesh_id << " LOD " << lod << ", size: " << size << LL_ENDL;
- }
- else
- {
- // Ignore failures for anomalously large data
- 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;
+ LLAppViewer::instance()->outOfMemorySoftQuit();
+ } // else ignore failures for anomalously large data
+ LLMutexLock lock(mMutex);
+ mUnavailableQ.push_back(LODRequest(mesh_params, lod));
+ return true;
}
LLMeshRepository::sCacheBytesRead += size;
++LLMeshRepository::sCacheReads;