Bug 1323155 - fix data race in mCompletionPromise. r=gerald
MozReview-Commit-ID: J2TVNWvx9pb
--- a/xpcom/threads/MozPromise.h
+++ b/xpcom/threads/MozPromise.h
@@ -623,35 +623,41 @@ public:
MOZ_MUST_USE RefPtr<MozPromise>
ThenPromise(AbstractThread* aResponseThread, const char* aCallSite, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
{
using ThenType = MethodThenValue<ThisType, ResolveMethodType, RejectMethodType>;
RefPtr<ThenValueBase> thenValue = new ThenType(
aResponseThread, aThisVal, aResolveMethod, aRejectMethod, aCallSite);
// mCompletionPromise must be created before ThenInternal() to avoid race.
- thenValue->mCompletionPromise = new MozPromise::Private(
+ RefPtr<MozPromise> p = new MozPromise::Private(
"<completion promise>", true /* aIsCompletionPromise */);
+ thenValue->mCompletionPromise = p;
+ // Note ThenInternal() might nullify mCompletionPromise before return.
+ // So we need to return p instead of mCompletionPromise.
ThenInternal(aResponseThread, thenValue, aCallSite);
- return thenValue->mCompletionPromise;
+ return p;
}
template<typename ResolveFunction, typename RejectFunction>
MOZ_MUST_USE RefPtr<MozPromise>
ThenPromise(AbstractThread* aResponseThread, const char* aCallSite,
ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
{
using ThenType = FunctionThenValue<ResolveFunction, RejectFunction>;
RefPtr<ThenValueBase> thenValue = new ThenType(
aResponseThread, Move(aResolveFunction), Move(aRejectFunction), aCallSite);
// mCompletionPromise must be created before ThenInternal() to avoid race.
- thenValue->mCompletionPromise = new MozPromise::Private(
+ RefPtr<MozPromise> p = new MozPromise::Private(
"<completion promise>", true /* aIsCompletionPromise */);
+ thenValue->mCompletionPromise = p;
+ // Note ThenInternal() might nullify mCompletionPromise before return.
+ // So we need to return p instead of mCompletionPromise.
ThenInternal(aResponseThread, thenValue, aCallSite);
- return thenValue->mCompletionPromise;
+ return p;
}
void ChainTo(already_AddRefed<Private> aChainedPromise, const char* aCallSite)
{
MutexAutoLock lock(mMutex);
MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveRequest);
mHaveRequest = true;
RefPtr<Private> chainedPromise = aChainedPromise;