Bug 745662 - Trigger a fatal release-time crash when the discard tracker is used off the main thread. r=joe
authorJustin Lebar <justin.lebar@gmail.com>
Wed, 18 Apr 2012 11:30:42 +1000
changeset 96725 b938f2e550c04e81e9a569eee4893b90767d9fe5
parent 95580 3a9629092a5f6f17f83913de422fd41a5c9f71d7
child 96726 b577f8acc6f726c480dd601c37aaf8f9b3904096
push id173
push userlsblakk@mozilla.com
push dateFri, 24 Aug 2012 15:39:16 +0000
treeherdermozilla-release@bcc45eb1fb41 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs745662
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 745662 - Trigger a fatal release-time crash when the discard tracker is used off the main thread. r=joe
image/src/DiscardTracker.cpp
image/src/DiscardTracker.h
--- a/image/src/DiscardTracker.cpp
+++ b/image/src/DiscardTracker.cpp
@@ -40,16 +40,18 @@ DiscardTimeoutChangedCallback(const char
 {
   DiscardTracker::ReloadTimeout();
   return 0;
 }
 
 nsresult
 DiscardTracker::Reset(Node *node)
 {
+  EnsureMainThread();
+
   // We shouldn't call Reset() with a null |img| pointer, on images which can't
   // be discarded, or on animated images (which should be marked as
   // non-discardable, anyway).
   MOZ_ASSERT(node->img);
   MOZ_ASSERT(node->img->CanDiscard());
   MOZ_ASSERT(!node->img->mAnim);
 
   // Initialize the first time through.
@@ -79,41 +81,47 @@ DiscardTracker::Reset(Node *node)
   NS_ENSURE_SUCCESS(rv,rv);
 
   return NS_OK;
 }
 
 void
 DiscardTracker::Remove(Node *node)
 {
+  EnsureMainThread();
+
   if (node->isInList())
     node->remove();
 
   if (sDiscardableImages.isEmpty())
     DisableTimer();
 }
 
 /**
  * Shut down the tracker, deallocating the timer.
  */
 void
 DiscardTracker::Shutdown()
 {
+  EnsureMainThread();
+
   if (sTimer) {
     sTimer->Cancel();
     sTimer = NULL;
   }
 }
 
 /*
  * Discard all the images we're tracking.
  */
 void
 DiscardTracker::DiscardAll()
 {
+  EnsureMainThread();
+
   if (!sInitialized)
     return;
 
   // Be careful: Calling Discard() on an image might cause it to be removed
   // from the list!
   Node *n;
   while ((n = sDiscardableImages.popFirst())) {
     n->img->Discard();
@@ -121,26 +129,39 @@ DiscardTracker::DiscardAll()
 
   // The list is empty, so there's no need to leave the timer on.
   DisableTimer();
 }
 
 void
 DiscardTracker::InformAllocation(PRInt64 bytes)
 {
+  EnsureMainThread();
+
   // This function is called back e.g. from RasterImage::Discard(); be careful!
 
   sCurrentDecodedImageBytes += bytes;
   MOZ_ASSERT(sCurrentDecodedImageBytes >= 0);
 
   // If we're using too much memory for decoded images, MaybeDiscardSoon will
   // enqueue a callback to discard some images.
   MaybeDiscardSoon();
 }
 
+void
+DiscardTracker::EnsureMainThread()
+{
+  // NS_RUNTIMEABORT is a fatal crash even in release builds.  We need to crash
+  // release builds here in order to investigate bug 745141 -- we're being
+  // called from off main thread, but we don't know how!
+  if (!NS_IsMainThread()) {
+    NS_RUNTIMEABORT("Must be on main thread!");
+  }
+}
+
 /**
  * Initialize the tracker.
  */
 nsresult
 DiscardTracker::Initialize()
 {
   // Watch the timeout pref for changes.
   Preferences::RegisterCallback(DiscardTimeoutChangedCallback,
--- a/image/src/DiscardTracker.h
+++ b/image/src/DiscardTracker.h
@@ -95,16 +95,18 @@ class DiscardTracker
     static nsresult Initialize();
     static void ReloadTimeout();
     static nsresult EnableTimer();
     static void DisableTimer();
     static void MaybeDiscardSoon();
     static void TimerCallback(nsITimer *aTimer, void *aClosure);
     static void DiscardNow();
 
+    static void EnsureMainThread();
+
     static LinkedList<Node> sDiscardableImages;
     static nsCOMPtr<nsITimer> sTimer;
     static bool sInitialized;
     static bool sTimerOn;
     static bool sDiscardRunnablePending;
     static PRInt64 sCurrentDecodedImageBytes;
     static PRUint32 sMinDiscardTimeoutMs;
     static PRUint32 sMaxDecodedImageKB;