backport Bug 1739421: Use kungFuDeathGrip when firing a timer r=bwc a=RyanVM

This commit is contained in:
roytam1 2021-12-14 22:46:33 +08:00
commit eb0082ecaa

View file

@ -433,11 +433,13 @@ nsTimerImpl::Fire(int32_t aGeneration)
uint8_t oldType; uint8_t oldType;
uint32_t oldDelay; uint32_t oldDelay;
TimeStamp oldTimeout; TimeStamp oldTimeout;
nsCOMPtr<nsITimer> timer;
{ {
MutexAutoLock lock(mMutex);
// Don't fire callbacks or fiddle with refcounts when the mutex is locked. // 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. // If some other thread Cancels/Inits after this, they're just too late.
MutexAutoLock lock(mMutex);
if (aGeneration != mGeneration) { if (aGeneration != mGeneration) {
return; return;
} }
@ -446,6 +448,10 @@ nsTimerImpl::Fire(int32_t aGeneration)
oldType = mType; oldType = mType;
oldDelay = mDelay; oldDelay = mDelay;
oldTimeout = mTimeout; 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", PROFILER_LABEL("Timer", "Fire",
@ -475,13 +481,13 @@ nsTimerImpl::Fire(int32_t aGeneration)
switch (mCallbackDuringFire.mType) { switch (mCallbackDuringFire.mType) {
case Callback::Type::Function: case Callback::Type::Function:
mCallbackDuringFire.mCallback.c(mITimer, mCallbackDuringFire.mClosure); mCallbackDuringFire.mCallback.c(timer, mCallbackDuringFire.mClosure);
break; break;
case Callback::Type::Interface: case Callback::Type::Interface:
mCallbackDuringFire.mCallback.i->Notify(mITimer); mCallbackDuringFire.mCallback.i->Notify(timer);
break; break;
case Callback::Type::Observer: case Callback::Type::Observer:
mCallbackDuringFire.mCallback.o->Observe(mITimer, NS_TIMER_CALLBACK_TOPIC, mCallbackDuringFire.mCallback.o->Observe(timer, NS_TIMER_CALLBACK_TOPIC,
nullptr); nullptr);
break; break;
default: default: