diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 427c6a512b16..c6bcc0bde065 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -342,6 +342,7 @@ FetchDriver::FetchDriver(SafeRefPtr aRequest, : mPrincipal(aPrincipal), mLoadGroup(aLoadGroup), mRequest(std::move(aRequest)), + mODAMutex("FetchDriver::mODAMutex"), mMainThreadEventTarget(aMainThreadEventTarget), mCookieJarSettings(aCookieJarSettings), mPerformanceStorage(aPerformanceStorage), @@ -1384,7 +1385,10 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream, uint64_t aOffset, uint32_t aCount) { // NB: This can be called on any thread! But we're guaranteed that it is // called between OnStartRequest and OnStopRequest, so we don't need to worry - // about races. + // about races for the members accessed in OnStartRequest, OnStopRequest, + // FailWithNetworkError and member functions accessed before opening the + // channel. However, we have a possibility of a race from + // FetchDriverAbortActions if (!mPipeOutputStream) { // We ignore the body for HEAD/CONNECT requests. @@ -1398,9 +1402,13 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInputStream, if (mNeedToObserveOnDataAvailable) { mNeedToObserveOnDataAvailable = false; - if (mObserver) { + RefPtr observer; + { + MutexAutoLock lock(mODAMutex); // Need to keep mObserver alive. - RefPtr observer = mObserver; + observer = mObserver; + } + if (observer) { if (NS_IsMainThread()) { observer->OnDataAvailable(); } else { @@ -1796,8 +1804,13 @@ void FetchDriver::RunAbortAlgorithm() { FetchDriverAbortActions(Signal()); } void FetchDriver::FetchDriverAbortActions(AbortSignalImpl* aSignalImpl) { MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread()); + RefPtr observer; + { + MutexAutoLock lock(mODAMutex); + observer = std::move(mObserver); + } - if (mObserver) { + if (observer) { #ifdef DEBUG mResponseAvailableCalled = true; #endif @@ -1805,8 +1818,7 @@ void FetchDriver::FetchDriverAbortActions(AbortSignalImpl* aSignalImpl) { if (aSignalImpl) { reason.set(aSignalImpl->RawReason()); } - mObserver->OnResponseEnd(FetchDriverObserver::eAborted, reason); - mObserver = nullptr; + observer->OnResponseEnd(FetchDriverObserver::eAborted, reason); } if (mChannel) { diff --git a/dom/fetch/FetchDriver.h b/dom/fetch/FetchDriver.h index 4184828cd5d2..5c8b88c1b4d5 100644 --- a/dom/fetch/FetchDriver.h +++ b/dom/fetch/FetchDriver.h @@ -18,6 +18,7 @@ #include "mozilla/dom/SerializedStackHolder.h" #include "mozilla/dom/SRIMetadata.h" #include "mozilla/RefPtr.h" +#include "mozilla/Mutex.h" #include "mozilla/UniquePtr.h" #include "mozilla/DebugOnly.h" @@ -155,6 +156,13 @@ class FetchDriver final : public nsIChannelEventSink, SafeRefPtr mRequest; SafeRefPtr mResponse; nsCOMPtr mPipeOutputStream; + + // mutex to prevent race between OnDataAvailable (OMT) and main thread + // functions + Mutex mODAMutex; + // access to mObserver can race between FetchDriverAbortActions (main thread) + // and OnDataAvailable (OMT) + // See Bug 1810805 RefPtr mObserver; RefPtr mDocument; nsCOMPtr mCSPEventListener;