diff options
| author | AndreyL ProductEngine <alihatskiy@productengine.com> | 2016-10-19 02:09:47 +0300 | 
|---|---|---|
| committer | AndreyL ProductEngine <alihatskiy@productengine.com> | 2016-10-19 02:09:47 +0300 | 
| commit | 2e52d12ef1ecc53f1affdf7b6d2150e9256eee65 (patch) | |
| tree | 8b73372ba63049b0ef9c5ce42bd78d5f5e01cc6b | |
| parent | f75ea457c836d73d6bdbbeed77536c74c1482f29 (diff) | |
MAINT-6819 Fix for LLTextureCacheRemoteWorker::doWrite crash
| -rw-r--r-- | indra/newview/lltexturecache.cpp | 167 | 
1 files changed, 100 insertions, 67 deletions
| diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 36c4f0d516..a541273621 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -547,10 +547,18 @@ bool LLTextureCacheRemoteWorker::doWrite()  	// First state / stage : check that what we're trying to cache is in an OK shape  	if (mState == INIT)  	{ -		llassert_always(mOffset == 0);	// We currently do not support write offsets -		llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative... -		llassert_always(mImageSize >= mDataSize); -		mState = CACHE; +		if ((mOffset != 0) // We currently do not support write offsets +			|| (mDataSize <= 0) // Things will go badly wrong if mDataSize is nul or negative... +			|| (mImageSize < mDataSize)) +		{ +			LL_WARNS() << "INIT state check failed" << LL_ENDL; +			mDataSize = -1; // failed +			done = true; +		} +		else +		{ +			mState = CACHE; +		}  	}  	// No LOCAL state for write(): because it doesn't make much sense to cache a local file... @@ -559,7 +567,7 @@ bool LLTextureCacheRemoteWorker::doWrite()  	if (!done && (mState == CACHE))  	{  		bool alreadyCached = false; -		LLTextureCache::Entry entry ; +		LLTextureCache::Entry entry;  		// Checks if this image is already in the entry list  		idx = mCache->getHeaderCacheEntry(mID, entry); @@ -571,107 +579,132 @@ bool LLTextureCacheRemoteWorker::doWrite()  				// (almost always) write to the fast cache.  				if (mRawImage->getDataSize())  				{ -				llassert_always(mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel)); +					if(!mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel)) +					{ +						LL_WARNS() << "writeToFastCache failed" << LL_ENDL; +						mDataSize = -1; // failed +						done = true; +					} +				}  			}  		} -		}  		else  		{  			alreadyCached = mCache->updateEntry(idx, entry, mImageSize, mDataSize); // update the existing entry.  		} -		if (idx < 0) -		{ -			LL_WARNS() << "LLTextureCacheWorker: "  << mID -					<< " Unable to create header entry for writing!" << LL_ENDL; -			mDataSize = -1; // failed -			done = true; -		} -		else +		if (!done)  		{ -			if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)) +			if (idx < 0)  			{ -				// Small texture already cached case: we're done with writing +				LL_WARNS() << "LLTextureCacheWorker: " << mID +					<< " Unable to create header entry for writing!" << LL_ENDL; +				mDataSize = -1; // failed  				done = true;  			}  			else  			{ -				// If the texture has already been cached, we don't resave the header and go directly to the body part -				mState = alreadyCached ? BODY : HEADER; +				if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)) +				{ +					// Small texture already cached case: we're done with writing +					done = true; +				} +				else +				{ +					// If the texture has already been cached, we don't resave the header and go directly to the body part +					mState = alreadyCached ? BODY : HEADER; +				}  			}  		}  	} +  	// Third stage / state : write the header record in the header file (texture.cache)  	if (!done && (mState == HEADER))  	{ -		llassert_always(idx >= 0);	// we need an entry here or storing the header makes no sense -		S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE;	// skip to the correct spot in the header file -		S32 size = TEXTURE_CACHE_ENTRY_SIZE;			// record size is fixed for the header -		S32 bytes_written; - -		if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE) +		if (idx < 0) // we need an entry here or storing the header makes no sense  		{ -			// We need to write a full record in the header cache so, if the amount of data is smaller -			// than a record, we need to transfer the data to a buffer padded with 0 and write that -			U8* padBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_CACHE_ENTRY_SIZE); -			memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE);		// Init with zeros -			memcpy(padBuffer, mWriteData, mDataSize);			// Copy the write buffer -			bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); -			FREE_MEM(LLImageBase::getPrivatePool(), padBuffer); +			LL_WARNS() << "index check failed" << LL_ENDL; +			mDataSize = -1; // failed +			done = true;  		}  		else  		{ -			// Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file -			bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); -		} +			S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE;	// skip to the correct spot in the header file +			S32 size = TEXTURE_CACHE_ENTRY_SIZE;			// record size is fixed for the header +			S32 bytes_written; -		if (bytes_written <= 0) -		{ -			LL_WARNS() << "LLTextureCacheWorker: "  << mID +			if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE) +			{ +				// We need to write a full record in the header cache so, if the amount of data is smaller +				// than a record, we need to transfer the data to a buffer padded with 0 and write that +				U8* padBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_CACHE_ENTRY_SIZE); +				memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE);		// Init with zeros +				memcpy(padBuffer, mWriteData, mDataSize);			// Copy the write buffer +				bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); +				FREE_MEM(LLImageBase::getPrivatePool(), padBuffer); +			} +			else +			{ +				// Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file +				bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); +			} + +			if (bytes_written <= 0) +			{ +				LL_WARNS() << "LLTextureCacheWorker: " << mID  					<< " Unable to write header entry!" << LL_ENDL; -			mDataSize = -1; // failed -			done = true; -		} +				mDataSize = -1; // failed +				done = true; +			} -		// If we wrote everything (may be more with padding) in the header cache,  -		// we're done so we don't have a body to store -		if (mDataSize <= bytes_written) -		{ -			done = true; -		} -		else -		{ -			mState = BODY; +			// If we wrote everything (may be more with padding) in the header cache,  +			// we're done so we don't have a body to store +			if (mDataSize <= bytes_written) +			{ +				done = true; +			} +			else +			{ +				mState = BODY; +			}  		}  	}  	// Fourth stage / state : write the body file, i.e. the rest of the texture in a "UUID" file name  	if (!done && (mState == BODY))  	{ -		llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE);	// wouldn't make sense to be here otherwise... -		S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; -		 +		if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) // wouldn't make sense to be here otherwise...  		{ -			// build the cache file name from the UUID -			std::string filename = mCache->getTextureFileName(mID);			 -// 			LL_INFOS() << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << LL_ENDL; -			S32 bytes_written = LLAPRFile::writeEx(	filename,  -													mWriteData + TEXTURE_CACHE_ENTRY_SIZE, -													0, file_size, -													mCache->getLocalAPRFilePool()); -			if (bytes_written <= 0) +			LL_WARNS() << "mDataSize check failed" << LL_ENDL; +			mDataSize = -1; // failed +			done = true; +		} +		else +		{ +			S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; +  			{ -				LL_WARNS() << "LLTextureCacheWorker: "  << mID +				// build the cache file name from the UUID +				std::string filename = mCache->getTextureFileName(mID); +				// 			LL_INFOS() << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << LL_ENDL; +				S32 bytes_written = LLAPRFile::writeEx(filename, +													   mWriteData + TEXTURE_CACHE_ENTRY_SIZE, +													   0, file_size, +													   mCache->getLocalAPRFilePool()); +				if (bytes_written <= 0) +				{ +					LL_WARNS() << "LLTextureCacheWorker: " << mID  						<< " incorrect number of bytes written to body: " << bytes_written  						<< " / " << file_size << LL_ENDL; -				mDataSize = -1; // failed -				done = true; +					mDataSize = -1; // failed +					done = true; +				}  			} + +			// Nothing else to do at that point... +			done = true;  		} -		 -		// Nothing else to do at that point... -		done = true;  	}  	mRawImage = NULL; | 
