viewer#2071 Soft quit on 'out of memory' for meshes #2
parent
c4ff0b4889
commit
c5d2e92089
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue