Bug 795940 - Always hold on to a reference to our image from a ScaleRequest so it can't delete itself while we're outstanding. r=jlebar
☠☠ backed out by 9737260d1647 ☠ ☠
authorJoe Drew <joe@drew.ca>
Wed, 03 Oct 2012 14:29:33 -0400
changeset 109205 134f5b1d6d507199a8cc4be955b186fdcf27a984
parent 109204 1f6b48dea5fc708fc8c63b1cb84781cc04de909a
child 109206 6925601f42997b18e73e08b3c6e17fe41385337f
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersjlebar
bugs795940
milestone18.0a1
Bug 795940 - Always hold on to a reference to our image from a ScaleRequest so it can't delete itself while we're outstanding. r=jlebar
image/src/RasterImage.cpp
image/src/RasterImage.h
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -229,18 +229,18 @@ RasterImage::RasterImage(imgStatusTracke
   mMultipart(false),
   mDiscardable(false),
   mHasSourceData(false),
   mDecoded(false),
   mHasBeenDecoded(false),
   mInDecoder(false),
   mAnimationFinished(false),
   mFinishing(false),
-  mScaleRequest(this),
-  mInUpdateImageContainer(false)
+  mInUpdateImageContainer(false),
+  mScaleRequest(this)
 {
   // Set up the discard tracker node.
   mDiscardTrackerNode.img = this;
   Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(0);
 
   // Statistics
   num_containers++;
 
@@ -2709,16 +2709,20 @@ void
 RasterImage::ScaleWorker::RequestScale(RasterImage* aImg)
 {
   mRequestsMutex.AssertCurrentThreadOwns();
 
   ScaleRequest* request = &aImg->mScaleRequest;
   if (request->isInList())
     return;
 
+  // While the request is outstanding, we hold a reference to it so it won't be
+  // deleted from under us (and, since it owns us, so we won't be deleted).
+  request->kungFuDeathGrip = request->image;
+
   mScaleRequests.insertBack(request);
 
   if (!sScaleWorkerThread) {
     NS_NewThread(getter_AddRefs(sScaleWorkerThread), this, NS_DISPATCH_NORMAL);
     ClearOnShutdown(&sScaleWorkerThread);
   }
   else {
     sScaleWorkerThread->Dispatch(this, NS_DISPATCH_NORMAL);
@@ -2753,16 +2757,21 @@ RasterImage::DrawWorker::Run()
     }
     nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(request->image->mObserver));
     if (request->done && observer) {
       imgFrame *scaledFrame = request->dstFrame.get();
       scaledFrame->ImageUpdated(scaledFrame->GetRect());
       nsIntRect frameRect = request->srcFrame->GetRect();
       observer->FrameChanged(nullptr, request->image, &frameRect);
     }
+    if (request->done) {
+      // We are now done with this image, so we can release our reference.
+      // THIS CAN DELETE THE REQUEST!
+      request->kungFuDeathGrip = nullptr;
+    }
   }
 
   return NS_OK;
 }
 
 void
 RasterImage::DrawWorker::RequestDraw(RasterImage* aImg)
 {
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -506,16 +506,17 @@ private:
         srcDataLocked = false;
       }
       return success;
     }
 
     static void Stop(RasterImage* aImg);
 
     RasterImage* const image;
+    nsRefPtr<RasterImage> kungFuDeathGrip;
     imgFrame *srcFrame;
     nsAutoPtr<imgFrame> dstFrame;
     gfxSize scale;
     bool done;
     bool stopped;
     bool srcDataLocked;
   };