summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiaohong Bao <bao@lindenlab.com>2010-08-06 09:29:33 -0600
committerXiaohong Bao <bao@lindenlab.com>2010-08-06 09:29:33 -0600
commit4682264eadc3c3a4dc09e64fc5ad74cb0657639e (patch)
tree550a956300b2ab2f1cd72e35e032675db4b3c572
parent0e673902f4d3ba257299cfc9552dcbf4977cf4a9 (diff)
EXT-8447: FIXED: crash at LLTextureCache::writeEntryToHeaderImmediately(int,LLTextureCache::Entry &,bool) [secondlife-bin lltexturecache.cpp]
-rw-r--r--indra/llcommon/llapr.cpp12
-rw-r--r--indra/newview/lltexturecache.cpp87
-rw-r--r--indra/newview/lltexturecache.h7
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);