diff options
author | Xiaohong Bao <bao@lindenlab.com> | 2010-08-06 09:29:33 -0600 |
---|---|---|
committer | Xiaohong Bao <bao@lindenlab.com> | 2010-08-06 09:29:33 -0600 |
commit | 4682264eadc3c3a4dc09e64fc5ad74cb0657639e (patch) | |
tree | 550a956300b2ab2f1cd72e35e032675db4b3c572 | |
parent | 0e673902f4d3ba257299cfc9552dcbf4977cf4a9 (diff) |
EXT-8447: FIXED: crash at LLTextureCache::writeEntryToHeaderImmediately(int,LLTextureCache::Entry &,bool) [secondlife-bin lltexturecache.cpp]
-rw-r--r-- | indra/llcommon/llapr.cpp | 12 | ||||
-rw-r--r-- | indra/newview/lltexturecache.cpp | 87 | ||||
-rw-r--r-- | indra/newview/lltexturecache.h | 7 |
3 files changed, 90 insertions, 16 deletions
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 7330b00bcf..dca4cf7c3f 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -417,7 +417,11 @@ apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool) // File I/O S32 LLAPRFile::read(void *buf, S32 nbytes) { - llassert_always(mFile) ; + if(!mFile) + { + llwarns << "apr mFile is removed by somebody else. Can not read." << llendl ; + return 0; + } apr_size_t sz = nbytes; apr_status_t s = apr_file_read(mFile, buf, &sz); @@ -435,7 +439,11 @@ S32 LLAPRFile::read(void *buf, S32 nbytes) S32 LLAPRFile::write(const void *buf, S32 nbytes) { - llassert_always(mFile) ; + if(!mFile) + { + llwarns << "apr mFile is removed by somebody else. Can not write." << llendl ; + return 0; + } apr_size_t sz = nbytes; apr_status_t s = apr_file_write(mFile, buf, &sz); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 403692951f..952f893015 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -998,7 +998,11 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset) void LLTextureCache::closeHeaderEntriesFile() { - llassert_always(mHeaderAPRFile != NULL); + if(!mHeaderAPRFile) + { + return ; + } + delete mHeaderAPRFile; mHeaderAPRFile = NULL; } @@ -1115,7 +1119,7 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create } //mHeaderMutex is locked before calling this. -void LLTextureCache::writeEntryToHeaderImmediately(S32 idx, Entry& entry, bool write_header) +void LLTextureCache::writeEntryToHeaderImmediately(S32& idx, Entry& entry, bool write_header) { LLAPRFile* aprfile ; S32 bytes_written ; @@ -1124,7 +1128,13 @@ void LLTextureCache::writeEntryToHeaderImmediately(S32 idx, Entry& entry, bool w { aprfile = openHeaderEntriesFile(false, 0); bytes_written = aprfile->write((U8*)&mHeaderEntriesInfo, sizeof(EntriesInfo)) ; - llassert_always(bytes_written == sizeof(EntriesInfo)); + if(bytes_written != sizeof(EntriesInfo)) + { + clearCorruptedCache() ; //clear the cache. + idx = -1 ;//mark the idx invalid. + return ; + } + mHeaderAPRFile->seek(APR_SET, offset); } else @@ -1132,19 +1142,31 @@ void LLTextureCache::writeEntryToHeaderImmediately(S32 idx, Entry& entry, bool w aprfile = openHeaderEntriesFile(false, offset); } bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry)); - llassert_always(bytes_written == sizeof(Entry)); + if(bytes_written != sizeof(Entry)) + { + clearCorruptedCache() ; //clear the cache. + idx = -1 ;//mark the idx invalid. + + return ; + } + closeHeaderEntriesFile(); mUpdatedEntryMap.erase(idx) ; } //mHeaderMutex is locked before calling this. -void LLTextureCache::readEntryFromHeaderImmediately(S32 idx, Entry& entry) +void LLTextureCache::readEntryFromHeaderImmediately(S32& idx, Entry& entry) { S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); LLAPRFile* aprfile = openHeaderEntriesFile(true, offset); S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry)); - llassert_always(bytes_read == sizeof(Entry)); closeHeaderEntriesFile(); + + if(bytes_read != sizeof(Entry)) + { + clearCorruptedCache() ; //clear the cache. + idx = -1 ;//mark the idx invalid. + } } //mHeaderMutex is locked before calling this. @@ -1169,7 +1191,7 @@ void LLTextureCache::updateEntryTimeStamp(S32 idx, Entry& entry) } //update an existing entry, write to header file immediately. -bool LLTextureCache::updateEntry(S32 idx, Entry& entry, S32 new_image_size, S32 new_data_size) +bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 new_data_size) { S32 new_body_size = llmax(0, new_data_size - TEXTURE_CACHE_ENTRY_SIZE) ; @@ -1240,6 +1262,10 @@ U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) { aprfile = openHeaderEntriesFile(false, 0); updatedHeaderEntriesFile() ; + if(!aprfile) + { + return 0; + } aprfile->seek(APR_SET, (S32)sizeof(EntriesInfo)); } for (U32 idx=0; idx<num_entries; idx++) @@ -1281,7 +1307,11 @@ void LLTextureCache::writeEntriesAndClose(const std::vector<Entry>& entries) for (S32 idx=0; idx<num_entries; idx++) { S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry)); - llassert_always(bytes_written == sizeof(Entry)); + if(bytes_written != sizeof(Entry)) + { + clearCorruptedCache() ; //clear the cache. + return ; + } } closeHeaderEntriesFile(); } @@ -1307,7 +1337,11 @@ void LLTextureCache::updatedHeaderEntriesFile() //entriesInfo mHeaderAPRFile->seek(APR_SET, 0); S32 bytes_written = mHeaderAPRFile->write((U8*)&mHeaderEntriesInfo, sizeof(EntriesInfo)) ; - llassert_always(bytes_written == sizeof(EntriesInfo)); + if(bytes_written != sizeof(EntriesInfo)) + { + clearCorruptedCache() ; //clear the cache. + return ; + } //write each updated entry S32 entry_size = (S32)sizeof(Entry) ; @@ -1323,7 +1357,11 @@ void LLTextureCache::updatedHeaderEntriesFile() } bytes_written = mHeaderAPRFile->write((void*)(&iter->second), entry_size); - llassert_always(bytes_written == entry_size); + if(bytes_written != entry_size) + { + clearCorruptedCache() ; //clear the cache. + return ; + } } mUpdatedEntryMap.clear() ; } @@ -1444,6 +1482,29 @@ void LLTextureCache::readHeaderCache() ////////////////////////////////////////////////////////////////////////////// +//the header mutex is locked before calling this. +void LLTextureCache::clearCorruptedCache() +{ + llwarns << "the texture cache is corrupted, need to be cleared." << llendl ; + + closeHeaderEntriesFile();//close possible file handler + purgeAllTextures(false) ; //clear the cache. + + if (!mReadOnly) //regenerate the directory tree if not exists. + { + LLFile::mkdir(mTexturesDirName); + + const char* subdirs = "0123456789abcdef"; + for (S32 i=0; i<16; i++) + { + std::string dirname = mTexturesDirName + gDirUtilp->getDirDelimiter() + subdirs[i]; + LLFile::mkdir(dirname); + } + } + + return ; +} + void LLTextureCache::purgeAllTextures(bool purge_directories) { if (!mReadOnly) @@ -1472,11 +1533,14 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) mTexturesSizeTotal = 0; mFreeList.clear(); mTexturesSizeTotal = 0; + mUpdatedEntryMap.clear(); // Info with 0 entries mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; mHeaderEntriesInfo.mEntries = 0; writeEntriesHeader(); + + llinfos << "The entire texture cache is cleared." << llendl ; } void LLTextureCache::purgeTextures(bool validate) @@ -1644,7 +1708,8 @@ S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, Entry& entry, S32 imag { updateEntry(idx, entry, imagesize, datasize); } - else // retry + + if(idx < 0) // retry { readHeaderCache(); // We couldn't write an entry, so refresh the LRU diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index 0fceee3011..f80be0056b 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -154,6 +154,7 @@ protected: private: void setDirNames(ELLPath location); void readHeaderCache(); + void clearCorruptedCache(); void purgeAllTextures(bool purge_directories); void purgeTextures(bool validate); LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset); @@ -161,12 +162,12 @@ private: void readEntriesHeader(); void writeEntriesHeader(); S32 openAndReadEntry(const LLUUID& id, Entry& entry, bool create); - bool updateEntry(S32 idx, Entry& entry, S32 new_image_size, S32 new_body_size); + bool updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 new_body_size); void updateEntryTimeStamp(S32 idx, Entry& entry) ; U32 openAndReadEntries(std::vector<Entry>& entries); void writeEntriesAndClose(const std::vector<Entry>& entries); - void readEntryFromHeaderImmediately(S32 idx, Entry& entry) ; - void writeEntryToHeaderImmediately(S32 idx, Entry& entry, bool write_header = false) ; + void readEntryFromHeaderImmediately(S32& idx, Entry& entry) ; + void writeEntryToHeaderImmediately(S32& idx, Entry& entry, bool write_header = false) ; void removeEntry(S32 idx, Entry& entry, std::string& filename); void removeCachedTexture(const LLUUID& id) ; S32 getHeaderCacheEntry(const LLUUID& id, Entry& entry); |