Bug 725885: Worker interval timers can be deleted prematurely. r=bent
authorKyle Huey <khuey@kylehuey.com>
Thu, 09 Feb 2012 19:03:11 -0800
changeset 86578 82779bfa0c2c5be83ea3978df672d9b55bb9bd1e
parent 86577 967b0dbce7e0fd464752f799ecda6999fea24c7b
child 86579 a5e20dbdb7db5d892008e074f42e1569a003e19f
push id22026
push userbmo@edmorley.co.uk
push dateFri, 10 Feb 2012 12:16:22 +0000
treeherdermozilla-central@417f1756b452 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs725885
milestone13.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 725885: Worker interval timers can be deleted prematurely. r=bent
dom/workers/WorkerPrivate.cpp
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3695,28 +3695,34 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
       NS_ASSERTION(timeoutIndex != PRUint32(-1),
                    "Should still be in the main list!");
 
       mTimeouts[timeoutIndex].forget();
       mTimeouts.RemoveElementAt(timeoutIndex);
 
       NS_ASSERTION(!mTimeouts.Contains(info), "Shouldn't have duplicates!");
 
-      info->mTargetTime += info->mInterval;
+      // NB: We must ensure that info->mTargetTime > now (where now is the
+      // now above, not literally TimeStamp::Now()) or we will remove the
+      // interval in the next loop below.
+      info->mTargetTime = NS_MAX(info->mTargetTime + info->mInterval,
+                                 now + TimeDuration::FromMilliseconds(1));
       mTimeouts.InsertElementSorted(info, comparator);
     }
   }
 
   // No longer possible to be called recursively.
   mRunningExpiredTimeouts = false;
 
   // Now remove canceled and expired timeouts from the main list.
   for (PRUint32 index = 0; index < mTimeouts.Length(); ) {
     nsAutoPtr<TimeoutInfo>& info = mTimeouts[index];
     if (info->mTargetTime <= now || info->mCanceled) {
+      NS_ASSERTION(!info->mIsInterval || info->mCanceled,
+                   "Interval timers can only be removed when canceled!");
       mTimeouts.RemoveElement(info);
     }
     else {
       index++;
     }
   }
 
   // Signal the parent that we're no longer using timeouts or reschedule the