Bug 1782181 - Part 1: Support canceling AsyncWait in nsMultiplexInputStream, r=asuth, a=dsmith
authorNika Layzell <nika@thelayzells.com>
Wed, 03 Aug 2022 19:36:29 +0000
changeset 696127 7b0014abc20e0d7302ec7eb0bf9c1abff21c07bd
parent 696126 4713888960a0d285706dfc4a20418a60fab2b102
child 696128 f028f909c84fdf1aaf6ee8c0bdba9d21a9c8873d
push id16931
push userdsmith@mozilla.com
push dateThu, 04 Aug 2022 18:37:42 +0000
treeherdermozilla-beta@f028f909c84f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth, dsmith
bugs1782181
milestone104.0
Bug 1782181 - Part 1: Support canceling AsyncWait in nsMultiplexInputStream, r=asuth, a=dsmith Previously nsMultiplexInputStream would not call `AsyncWait` again when the callback was cleared, meaning that the underlying wait wouldn't actually be cancelled. This patch changes the behaviour to more consistently forward the cancelling call to the underlying stream. There are still some cases where the call will not be cancelled if a read or other event caused the stream cursor to advance before canceling, however those should generally be uncommon. Differential Revision: https://phabricator.services.mozilla.com/D153628
xpcom/io/nsMultiplexInputStream.cpp
--- a/xpcom/io/nsMultiplexInputStream.cpp
+++ b/xpcom/io/nsMultiplexInputStream.cpp
@@ -822,27 +822,24 @@ nsMultiplexInputStream::AsyncWait(nsIInp
                    mAsyncWaitCallback != aCallback)) {
       return NS_ERROR_FAILURE;
     }
 
     mAsyncWaitCallback = aCallback;
     mAsyncWaitFlags = aFlags;
     mAsyncWaitRequestedCount = aRequestedCount;
     mAsyncWaitEventTarget = aEventTarget;
-
-    if (!mAsyncWaitCallback) {
-      return NS_OK;
-    }
   }
 
   return AsyncWaitInternal();
 }
 
 nsresult nsMultiplexInputStream::AsyncWaitInternal() {
   nsCOMPtr<nsIAsyncInputStream> stream;
+  nsIInputStreamCallback* asyncWaitCallback = nullptr;
   uint32_t asyncWaitFlags = 0;
   uint32_t asyncWaitRequestedCount = 0;
   nsCOMPtr<nsIEventTarget> asyncWaitEventTarget;
 
   {
     MutexAutoLock lock(mLock);
 
     // Let's take the first async stream if we are not already closed, and if
@@ -864,32 +861,35 @@ nsresult nsMultiplexInputStream::AsyncWa
         if (NS_FAILED(rv)) {
           return rv;
         }
 
         break;
       }
     }
 
+    asyncWaitCallback = mAsyncWaitCallback ? this : nullptr;
     asyncWaitFlags = mAsyncWaitFlags;
     asyncWaitRequestedCount = mAsyncWaitRequestedCount;
     asyncWaitEventTarget = mAsyncWaitEventTarget;
 
     MOZ_ASSERT_IF(stream, NS_SUCCEEDED(mStatus));
   }
 
   // If we are here it's because we are already closed, or if the current stream
   // is not async. In both case we have to execute the callback.
   if (!stream) {
-    AsyncWaitRunnable::Create(this, asyncWaitEventTarget);
+    if (asyncWaitCallback) {
+      AsyncWaitRunnable::Create(this, asyncWaitEventTarget);
+    }
     return NS_OK;
   }
 
-  return stream->AsyncWait(this, asyncWaitFlags, asyncWaitRequestedCount,
-                           asyncWaitEventTarget);
+  return stream->AsyncWait(asyncWaitCallback, asyncWaitFlags,
+                           asyncWaitRequestedCount, asyncWaitEventTarget);
 }
 
 NS_IMETHODIMP
 nsMultiplexInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream) {
   nsCOMPtr<nsIInputStreamCallback> callback;
 
   // When OnInputStreamReady is called, we could be in 2 scenarios:
   // a. there is something to read;