Bug 383553 - Crash on quit in nsTimerImpl::Release, r=dbaron sr=brendan
authorbenjamin@smedbergs.us
Thu, 09 Aug 2007 11:37:02 -0700
changeset 4410 3a31a8e78d3c7c568c1d51468028094b142aaeec
parent 4409 c3bd3cddf374c5fbbe44b68fbf932f00babbc6c2
child 4411 15dd05b600690a84f490b9ced34a697d01829569
push idunknown
push userunknown
push dateunknown
reviewersdbaron, brendan
bugs383553
milestone1.9a8pre
Bug 383553 - Crash on quit in nsTimerImpl::Release, r=dbaron sr=brendan
xpcom/threads/TimerThread.cpp
xpcom/threads/nsTimerImpl.cpp
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -69,21 +69,17 @@ TimerThread::~TimerThread()
 {
   if (mCondVar)
     PR_DestroyCondVar(mCondVar);
   if (mLock)
     PR_DestroyLock(mLock);
 
   mThread = nsnull;
 
-  PRInt32 n = mTimers.Count();
-  while (--n >= 0) {
-    nsTimerImpl *timer = static_cast<nsTimerImpl *>(mTimers[n]);
-    NS_RELEASE(timer);
-  }
+  NS_ASSERTION(mTimers.Count() == 0, "Timers remain in TimerThread::~TimerThread");
 }
 
 nsresult
 TimerThread::InitLocks()
 {
   NS_ASSERTION(!mLock, "InitLocks called twice?");
   mLock = PR_NewLock();
   if (!mLock)
@@ -327,17 +323,17 @@ NS_IMETHODIMP TimerThread::Run()
 
 nsresult TimerThread::AddTimer(nsTimerImpl *aTimer)
 {
   nsAutoLock lock(mLock);
 
   // Add the timer to our list.
   PRInt32 i = AddTimerInternal(aTimer);
   if (i < 0)
-    return NS_ERROR_OUT_OF_MEMORY;
+    return NS_ERROR_FAILURE;
 
   // Awaken the timer thread.
   if (mCondVar && mWaiting && i == 0)
     PR_NotifyCondVar(mCondVar);
 
   return NS_OK;
 }
 
@@ -379,16 +375,19 @@ nsresult TimerThread::RemoveTimer(nsTime
     PR_NotifyCondVar(mCondVar);
 
   return NS_OK;
 }
 
 // This function must be called from within a lock
 PRInt32 TimerThread::AddTimerInternal(nsTimerImpl *aTimer)
 {
+  if (mShutdown)
+    return -1;
+
   PRIntervalTime now = PR_IntervalNow();
   PRInt32 count = mTimers.Count();
   PRInt32 i = 0;
   for (; i < count; i++) {
     nsTimerImpl *timer = static_cast<nsTimerImpl *>(mTimers[i]);
 
     // Don't break till we have skipped any overdue timers.  Do not include
     // mTimeoutAdjustment here, because we are really trying to avoid calling
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -123,16 +123,17 @@ NS_IMETHODIMP_(nsrefcnt) nsTimerImpl::Re
   // Note that both approaches preclude a timer creator, and everyone else
   // except the TimerThread who might have a strong ref, from dropping all
   // their strong refs without implicitly canceling the timer.  Timers need
   // non-mTimers-element strong refs to stay alive.
 
   if (count == 1 && mArmed) {
     mCanceled = PR_TRUE;
 
+    NS_ASSERTION(gThread, "An armed timer exists after the thread timer stopped.");
     if (NS_SUCCEEDED(gThread->RemoveTimer(this)))
       return 0;
   }
 
   return count;
 }
 
 nsTimerImpl::nsTimerImpl() :