Bug 910881 - Do not call RasterImage::DoError off the main thread. r=jdm

--HG--
extra : rebase_source : 9d76763242a351dfbdcf8a35db98a5dceed0d838
This commit is contained in:
Seth Fowler 2013-09-12 14:40:16 -07:00
Родитель 5a86d36e71
Коммит 2ef014c792
2 изменённых файлов: 59 добавлений и 2 удалений

Просмотреть файл

@ -401,6 +401,7 @@ RasterImage::RasterImage(imgStatusTracker* aStatusTracker,
mFinishing(false),
mInUpdateImageContainer(false),
mWantFullDecode(false),
mPendingError(false),
mScaleRequest(nullptr)
{
// Set up the discard tracker node.
@ -2822,13 +2823,19 @@ RasterImage::DoError()
if (mError)
return;
// We can't safely handle errors off-main-thread, so dispatch a worker to do it.
if (!NS_IsMainThread()) {
HandleErrorWorker::DispatchIfNeeded(this);
return;
}
// If we're mid-decode, shut down the decoder.
if (mDecoder) {
MutexAutoLock lock(mDecodingMutex);
FinishedSomeDecoding(eShutdownIntent_Error);
}
// Put the container in an error state
// Put the container in an error state.
mError = true;
if (mDecodeRequest) {
@ -2841,6 +2848,30 @@ RasterImage::DoError()
LOG_CONTAINER_ERROR;
}
/* static */ void
RasterImage::HandleErrorWorker::DispatchIfNeeded(RasterImage* aImage)
{
if (!aImage->mPendingError) {
aImage->mPendingError = true;
nsRefPtr<HandleErrorWorker> worker = new HandleErrorWorker(aImage);
NS_DispatchToMainThread(worker);
}
}
RasterImage::HandleErrorWorker::HandleErrorWorker(RasterImage* aImage)
: mImage(aImage)
{
MOZ_ASSERT(mImage, "Should have image");
}
NS_IMETHODIMP
RasterImage::HandleErrorWorker::Run()
{
mImage->DoError();
return NS_OK;
}
// nsIInputStream callback to copy the incoming image data directly to the
// RasterImage without processing. The RasterImage is passed as the closure.
// Always reads everything it gets, even if the data is erroneous.
@ -3188,6 +3219,7 @@ RasterImage::DecodePool::DecodeJob::Run()
// this request to the back of the list.
else if (mImage->mDecoder &&
!mImage->mError &&
!mImage->mPendingError &&
!mImage->IsDecodeFinished() &&
bytesDecoded < mRequest->mBytesToDecode &&
bytesDecoded > 0) {

Просмотреть файл

@ -667,6 +667,11 @@ private: // data
// off a full decode.
bool mWantFullDecode:1;
// Set when a decode worker detects an error off-main-thread. Once the error
// is handled on the main thread, mError is set, but mPendingError is used to
// stop decode work immediately.
bool mPendingError:1;
// Decoding
nsresult WantDecodedFrames();
nsresult SyncDecode();
@ -699,8 +704,28 @@ private: // data
nsresult ShutdownDecoder(eShutdownIntent aIntent);
// Helpers
// Error handling.
void DoError();
class HandleErrorWorker : public nsRunnable
{
public:
/**
* Called from decoder threads when DoError() is called, since errors can't
* be handled safely off-main-thread. Dispatches an event which reinvokes
* DoError on the main thread if there isn't one already pending.
*/
static void DispatchIfNeeded(RasterImage* aImage);
NS_IMETHOD Run();
private:
HandleErrorWorker(RasterImage* aImage);
nsRefPtr<RasterImage> mImage;
};
// Helpers
bool CanDiscard();
bool CanForciblyDiscard();
bool DiscardingActive();