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); | 
