Bug 1343335 - Add asserts to check for null AbstractThread targets in MozPromise; r=bholley
authorKyle Machulis <kyle@nonpolynomial.com>
Tue, 28 Feb 2017 12:26:07 -0800
changeset 345207 f985ae4754e011848afe468dfd6d026a31b06347
parent 345206 dabb9120d849fec9dd6946ee4c43d15d0b9679ae
child 345208 547321d210ec1914212be67f2c4d77a8047094f2
push id87532
push userkmachulis@mozilla.com
push dateWed, 01 Mar 2017 04:34:54 +0000
treeherdermozilla-inbound@547321d210ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1343335
milestone54.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 1343335 - Add asserts to check for null AbstractThread targets in MozPromise; r=bholley AbstractThread::GetCurrent() can return null if a thread isn't a default AbstractThread (MainThread, etc). This doesn't get caught in MozPromise until we try to check for reliability of dispatching on the thread. Adding asserts to make things clearer on crashes. MozReview-Commit-ID: AQJwpdTUiHZ
xpcom/threads/MozPromise.h
--- a/xpcom/threads/MozPromise.h
+++ b/xpcom/threads/MozPromise.h
@@ -347,17 +347,19 @@ protected:
       RefPtr<ThenValueBase> mThenValue;
       RefPtr<MozPromise> mPromise;
     };
 
     ThenValueBase(AbstractThread* aResponseTarget,
                   const char* aCallSite)
       : mResponseTarget(aResponseTarget)
       , mCallSite(aCallSite)
-    { }
+    {
+      MOZ_ASSERT(aResponseTarget);
+    }
 
 #ifdef PROMISE_DEBUG
     ~ThenValueBase()
     {
       mMagic1 = 0;
       mMagic2 = 0;
     }
 #endif
@@ -690,16 +692,17 @@ protected:
     Maybe<ResolveRejectFunction> mResolveRejectFunction; // Only accessed and deleted on dispatch thread.
   };
 
 public:
   void ThenInternal(AbstractThread* aResponseThread, ThenValueBase* aThenValue,
                     const char* aCallSite)
   {
     PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic && mMagic4 == mMutex.mLock);
+    MOZ_ASSERT(aResponseThread);
     MutexAutoLock lock(mMutex);
     MOZ_ASSERT(aResponseThread->IsDispatchReliable());
     MOZ_DIAGNOSTIC_ASSERT(!IsExclusive || !mHaveRequest);
     mHaveRequest = true;
     PROMISE_LOG("%s invoking Then() [this=%p, aThenValue=%p, isPending=%d]",
                 aCallSite, this, aThenValue, (int) IsPending());
     if (!IsPending()) {
       aThenValue->Dispatch(this);
@@ -724,17 +727,20 @@ private:
 
     ThenCommand(AbstractThread* aResponseThread,
                 const char* aCallSite,
                 already_AddRefed<ThenValueBase> aThenValue,
                 MozPromise* aReceiver)
       : mResponseThread(aResponseThread)
       , mCallSite(aCallSite)
       , mThenValue(aThenValue)
-      , mReceiver(aReceiver) {}
+      , mReceiver(aReceiver)
+    {
+      MOZ_ASSERT(aResponseThread);
+    }
 
     ThenCommand(ThenCommand&& aOther) = default;
 
   public:
     ~ThenCommand()
     {
       // Issue the request now if the return value of Then() is not used.
       if (mThenValue) {
@@ -1238,16 +1244,18 @@ template<typename... Storages,
          typename PromiseType, typename ThisType, typename... ArgTypes,
          typename... ActualArgTypes>
 static RefPtr<PromiseType>
 InvokeAsyncImpl(AbstractThread* aTarget, ThisType* aThisVal,
                 const char* aCallerName,
                 RefPtr<PromiseType>(ThisType::*aMethod)(ArgTypes...),
                 ActualArgTypes&&... aArgs)
 {
+  MOZ_ASSERT(aTarget);
+
   typedef RefPtr<PromiseType>(ThisType::*MethodType)(ArgTypes...);
   typedef detail::MethodCall<PromiseType, MethodType, ThisType, Storages...> MethodCallType;
   typedef detail::ProxyRunnable<PromiseType, MethodType, ThisType, Storages...> ProxyRunnableType;
 
   MethodCallType* methodCall =
     new MethodCallType(aMethod, aThisVal, Forward<ActualArgTypes>(aArgs)...);
   RefPtr<typename PromiseType::Private> p = new (typename PromiseType::Private)(aCallerName);
   RefPtr<ProxyRunnableType> r = new ProxyRunnableType(p, methodCall);
@@ -1359,16 +1367,17 @@ static auto
 InvokeAsync(AbstractThread* aTarget, const char* aCallerName,
             AllowInvokeAsyncFunctionLVRef, Function&& aFunction)
   -> decltype(aFunction())
 {
   static_assert(IsRefcountedSmartPointer<decltype(aFunction())>::value
                 && IsMozPromise<typename RemoveSmartPointer<
                                            decltype(aFunction())>::Type>::value,
                 "Function object must return RefPtr<MozPromise>");
+  MOZ_ASSERT(aTarget);
   typedef typename RemoveSmartPointer<decltype(aFunction())>::Type PromiseType;
   typedef detail::ProxyFunctionRunnable<Function, PromiseType> ProxyRunnableType;
 
   RefPtr<typename PromiseType::Private> p =
     new (typename PromiseType::Private)(aCallerName);
   RefPtr<ProxyRunnableType> r =
     new ProxyRunnableType(p, Forward<Function>(aFunction));
   MOZ_ASSERT(aTarget->IsDispatchReliable());