Commit d3f389a3 authored by andreykproductengine's avatar andreykproductengine
Browse files

SL-12326 Textures' apr pool crash fix

parent 3d88b258
......@@ -838,6 +838,7 @@ LLTextureCache::LLTextureCache(bool threaded)
mFastCachePoolp(NULL),
mFastCachePadBuffer(NULL)
{
mHeaderAPRFilePoolp = new LLVolatileAPRPool(); // is_local = true, because this pool is for headers, headers are under own mutex
}
LLTextureCache::~LLTextureCache()
......@@ -846,6 +847,7 @@ LLTextureCache::~LLTextureCache()
writeUpdatedEntries() ;
delete mFastCachep;
delete mFastCachePoolp;
delete mHeaderAPRFilePoolp;
ll_aligned_free_16(mFastCachePadBuffer);
}
......@@ -1014,10 +1016,11 @@ void LLTextureCache::purgeCache(ELLPath location, bool remove_dir)
if(LLFile::isdir(mTexturesDirName))
{
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);
LLAPRFile::remove(file_name, getLocalAPRFilePool());
LLAPRFile::remove(file_name, mHeaderAPRFilePoolp);
purgeAllTextures(true);
}
......@@ -1094,7 +1097,7 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset)
{
llassert_always(mHeaderAPRFile == NULL);
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)
{
mHeaderAPRFile->seek(APR_SET, offset);
......@@ -1117,10 +1120,10 @@ void LLTextureCache::readEntriesHeader()
{
// mHeaderEntriesInfo initializes to default values so safe not to read it
llassert_always(mHeaderAPRFile == NULL);
if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool()))
if (LLAPRFile::isExist(mHeaderEntriesFileName, mHeaderAPRFilePoolp))
{
LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
getLocalAPRFilePool());
mHeaderAPRFilePoolp);
}
else //create an empty entries header.
{
......@@ -1152,7 +1155,7 @@ void LLTextureCache::writeEntriesHeader()
if (!mReadOnly)
{
LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
getLocalAPRFilePool());
mHeaderAPRFilePoolp);
}
}
......@@ -1832,7 +1835,8 @@ void LLTextureCache::purgeTextures(bool validate)
if (uuididx == validate_idx)
{
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)
{
LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize
......@@ -2231,7 +2235,7 @@ void LLTextureCache::openFastCache(bool first_time)
{
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))
{
mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
......@@ -2315,7 +2319,9 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id)
mTexturesSizeMap.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.
......@@ -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 (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;
}
......@@ -2347,7 +2356,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
if (file_maybe_exists)
{
LLAPRFile::remove(filename, getLocalAPRFilePool());
LLAPRFile::remove(filename, mHeaderAPRFilePoolp);
}
}
......
......@@ -139,7 +139,7 @@ class LLTextureCache : public LLWorkerThread
U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
U32 getMaxEntries() { return sCacheMaxEntries; };
BOOL isInCache(const LLUUID& id) ;
BOOL isInLocal(const LLUUID& id) ;
BOOL isInLocal(const LLUUID& id) ; //not thread safe at the moment
protected:
// Accessed by LLTextureCacheWorker
......@@ -190,6 +190,11 @@ class LLTextureCache : public LLWorkerThread
LLMutex mFastCacheMutex;
LLAPRFile* mHeaderAPRFile;
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;
handle_map_t mReaders;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment