summaryrefslogtreecommitdiff
path: root/xpcom/threads/nsTimerImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/threads/nsTimerImpl.cpp')
-rw-r--r--xpcom/threads/nsTimerImpl.cpp14
1 files changed, 10 insertions, 4 deletions
diff --git a/xpcom/threads/nsTimerImpl.cpp b/xpcom/threads/nsTimerImpl.cpp
index cac3e86929..2a3531a858 100644
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -433,11 +433,13 @@ nsTimerImpl::Fire(int32_t aGeneration)
uint8_t oldType;
uint32_t oldDelay;
TimeStamp oldTimeout;
+ nsCOMPtr<nsITimer> timer;
{
+ MutexAutoLock lock(mMutex);
+
// Don't fire callbacks or fiddle with refcounts when the mutex is locked.
// If some other thread Cancels/Inits after this, they're just too late.
- MutexAutoLock lock(mMutex);
if (aGeneration != mGeneration) {
// This timer got rescheduled or cancelled before we fired, so ignore this
// firing
@@ -448,6 +450,10 @@ nsTimerImpl::Fire(int32_t aGeneration)
oldType = mType;
oldDelay = mDelay;
oldTimeout = mTimeout;
+ // Ensure that the nsITimer does not unhook from the nsTimerImpl during
+ // Fire; this will cause null pointer crashes if the user of the timer drops
+ // its reference, and then uses the nsITimer* passed in the callback.
+ timer = mITimer;
}
PROFILER_LABEL("Timer", "Fire",
@@ -477,13 +483,13 @@ nsTimerImpl::Fire(int32_t aGeneration)
switch (mCallbackDuringFire.mType) {
case Callback::Type::Function:
- mCallbackDuringFire.mCallback.c(mITimer, mCallbackDuringFire.mClosure);
+ mCallbackDuringFire.mCallback.c(timer, mCallbackDuringFire.mClosure);
break;
case Callback::Type::Interface:
- mCallbackDuringFire.mCallback.i->Notify(mITimer);
+ mCallbackDuringFire.mCallback.i->Notify(timer);
break;
case Callback::Type::Observer:
- mCallbackDuringFire.mCallback.o->Observe(mITimer, NS_TIMER_CALLBACK_TOPIC,
+ mCallbackDuringFire.mCallback.o->Observe(timer, NS_TIMER_CALLBACK_TOPIC,
nullptr);
break;
default: