Skip to content
Snippets Groups Projects
Commit d3f389a3 authored by andreykproductengine's avatar andreykproductengine
Browse files

SL-12326 Textures' apr pool crash fix

parent 3d88b258
No related branches found
No related tags found
No related merge requests found
...@@ -838,6 +838,7 @@ LLTextureCache::LLTextureCache(bool threaded) ...@@ -838,6 +838,7 @@ LLTextureCache::LLTextureCache(bool threaded)
mFastCachePoolp(NULL), mFastCachePoolp(NULL),
mFastCachePadBuffer(NULL) mFastCachePadBuffer(NULL)
{ {
mHeaderAPRFilePoolp = new LLVolatileAPRPool(); // is_local = true, because this pool is for headers, headers are under own mutex
} }
LLTextureCache::~LLTextureCache() LLTextureCache::~LLTextureCache()
...@@ -846,6 +847,7 @@ LLTextureCache::~LLTextureCache() ...@@ -846,6 +847,7 @@ LLTextureCache::~LLTextureCache()
writeUpdatedEntries() ; writeUpdatedEntries() ;
delete mFastCachep; delete mFastCachep;
delete mFastCachePoolp; delete mFastCachePoolp;
delete mHeaderAPRFilePoolp;
ll_aligned_free_16(mFastCachePadBuffer); ll_aligned_free_16(mFastCachePadBuffer);
} }
...@@ -1014,10 +1016,11 @@ void LLTextureCache::purgeCache(ELLPath location, bool remove_dir) ...@@ -1014,10 +1016,11 @@ void LLTextureCache::purgeCache(ELLPath location, bool remove_dir)
if(LLFile::isdir(mTexturesDirName)) if(LLFile::isdir(mTexturesDirName))
{ {
std::string file_name = gDirUtilp->getExpandedFilename(location, entries_filename); std::string file_name = gDirUtilp->getExpandedFilename(location, entries_filename);
LLAPRFile::remove(file_name, getLocalAPRFilePool()); // mHeaderAPRFilePoolp because we are under header mutex, and can be in main thread
LLAPRFile::remove(file_name, mHeaderAPRFilePoolp);
file_name = gDirUtilp->getExpandedFilename(location, cache_filename); file_name = gDirUtilp->getExpandedFilename(location, cache_filename);
LLAPRFile::remove(file_name, getLocalAPRFilePool()); LLAPRFile::remove(file_name, mHeaderAPRFilePoolp);
purgeAllTextures(true); purgeAllTextures(true);
} }
...@@ -1094,7 +1097,7 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset) ...@@ -1094,7 +1097,7 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset)
{ {
llassert_always(mHeaderAPRFile == NULL); llassert_always(mHeaderAPRFile == NULL);
apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY; apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY;
mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, getLocalAPRFilePool()); mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, mHeaderAPRFilePoolp);
if(offset > 0) if(offset > 0)
{ {
mHeaderAPRFile->seek(APR_SET, offset); mHeaderAPRFile->seek(APR_SET, offset);
...@@ -1117,10 +1120,10 @@ void LLTextureCache::readEntriesHeader() ...@@ -1117,10 +1120,10 @@ void LLTextureCache::readEntriesHeader()
{ {
// mHeaderEntriesInfo initializes to default values so safe not to read it // mHeaderEntriesInfo initializes to default values so safe not to read it
llassert_always(mHeaderAPRFile == NULL); llassert_always(mHeaderAPRFile == NULL);
if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool())) if (LLAPRFile::isExist(mHeaderEntriesFileName, mHeaderAPRFilePoolp))
{ {
LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
getLocalAPRFilePool()); mHeaderAPRFilePoolp);
} }
else //create an empty entries header. else //create an empty entries header.
{ {
...@@ -1152,7 +1155,7 @@ void LLTextureCache::writeEntriesHeader() ...@@ -1152,7 +1155,7 @@ void LLTextureCache::writeEntriesHeader()
if (!mReadOnly) if (!mReadOnly)
{ {
LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
getLocalAPRFilePool()); mHeaderAPRFilePoolp);
} }
} }
...@@ -1832,7 +1835,8 @@ void LLTextureCache::purgeTextures(bool validate) ...@@ -1832,7 +1835,8 @@ void LLTextureCache::purgeTextures(bool validate)
if (uuididx == validate_idx) if (uuididx == validate_idx)
{ {
LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL; LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL;
S32 bodysize = LLAPRFile::size(filename, getLocalAPRFilePool()); // mHeaderAPRFilePoolp because this is under header mutex in main thread
S32 bodysize = LLAPRFile::size(filename, mHeaderAPRFilePoolp);
if (bodysize != entries[idx].mBodySize) if (bodysize != entries[idx].mBodySize)
{ {
LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize
...@@ -2231,7 +2235,7 @@ void LLTextureCache::openFastCache(bool first_time) ...@@ -2231,7 +2235,7 @@ void LLTextureCache::openFastCache(bool first_time)
{ {
mFastCachePadBuffer = (U8*)ll_aligned_malloc_16(TEXTURE_FAST_CACHE_ENTRY_SIZE); mFastCachePadBuffer = (U8*)ll_aligned_malloc_16(TEXTURE_FAST_CACHE_ENTRY_SIZE);
} }
mFastCachePoolp = new LLVolatileAPRPool(); mFastCachePoolp = new LLVolatileAPRPool(); // is_local= true by default, so not thread safe by default
if (LLAPRFile::isExist(mFastCacheFileName, mFastCachePoolp)) if (LLAPRFile::isExist(mFastCacheFileName, mFastCachePoolp))
{ {
mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ; mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
...@@ -2315,7 +2319,9 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id) ...@@ -2315,7 +2319,9 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id)
mTexturesSizeMap.erase(id); mTexturesSizeMap.erase(id);
} }
mHeaderIDMap.erase(id); mHeaderIDMap.erase(id);
LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); // We are inside header's mutex so mHeaderAPRFilePoolp is safe to use,
// but getLocalAPRFilePool() is not safe, it might be in use by worker
LLAPRFile::remove(getTextureFileName(id), mHeaderAPRFilePoolp);
} }
//called after mHeaderMutex is locked. //called after mHeaderMutex is locked.
...@@ -2327,7 +2333,10 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename) ...@@ -2327,7 +2333,10 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
{ {
if (entry.mBodySize == 0) // Always attempt to remove when mBodySize > 0. if (entry.mBodySize == 0) // Always attempt to remove when mBodySize > 0.
{ {
if (LLAPRFile::isExist(filename, getLocalAPRFilePool())) // Sanity check. Shouldn't exist when body size is 0. // Sanity check. Shouldn't exist when body size is 0.
// We are inside header's mutex so mHeaderAPRFilePoolp is safe to use,
// but getLocalAPRFilePool() is not safe, it might be in use by worker
if (LLAPRFile::isExist(filename, mHeaderAPRFilePoolp))
{ {
LL_WARNS("TextureCache") << "Entry has body size of zero but file " << filename << " exists. Deleting this file, too." << LL_ENDL; LL_WARNS("TextureCache") << "Entry has body size of zero but file " << filename << " exists. Deleting this file, too." << LL_ENDL;
} }
...@@ -2347,7 +2356,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename) ...@@ -2347,7 +2356,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
if (file_maybe_exists) if (file_maybe_exists)
{ {
LLAPRFile::remove(filename, getLocalAPRFilePool()); LLAPRFile::remove(filename, mHeaderAPRFilePoolp);
} }
} }
......
...@@ -139,7 +139,7 @@ class LLTextureCache : public LLWorkerThread ...@@ -139,7 +139,7 @@ class LLTextureCache : public LLWorkerThread
U32 getEntries() { return mHeaderEntriesInfo.mEntries; } U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
U32 getMaxEntries() { return sCacheMaxEntries; }; U32 getMaxEntries() { return sCacheMaxEntries; };
BOOL isInCache(const LLUUID& id) ; BOOL isInCache(const LLUUID& id) ;
BOOL isInLocal(const LLUUID& id) ; BOOL isInLocal(const LLUUID& id) ; //not thread safe at the moment
protected: protected:
// Accessed by LLTextureCacheWorker // Accessed by LLTextureCacheWorker
...@@ -190,6 +190,11 @@ class LLTextureCache : public LLWorkerThread ...@@ -190,6 +190,11 @@ class LLTextureCache : public LLWorkerThread
LLMutex mFastCacheMutex; LLMutex mFastCacheMutex;
LLAPRFile* mHeaderAPRFile; LLAPRFile* mHeaderAPRFile;
LLVolatileAPRPool* mFastCachePoolp; LLVolatileAPRPool* mFastCachePoolp;
// mLocalAPRFilePoolp is not thread safe and is meant only for workers
// howhever mHeaderEntriesFileName is accessed not from workers' threads
// so it needs own pool (not thread safe by itself, relies onto header's mutex)
LLVolatileAPRPool* mHeaderAPRFilePoolp;
typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t; typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
handle_map_t mReaders; handle_map_t mReaders;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment