Bug 1646933 - DelayedStartInputStream::AsyncWait is wrongly implemented, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Sun, 21 Jun 2020 20:53:54 +0000
changeset 536506 a91e8e8cd93f17fd341b8f20c0d8858a5e5a0b38
parent 536505 3fb7f441b1c1888ba1e37db1aeba8a247993c00a
child 536507 5078030eaeaff0978b2fd447e1a2ec081782d4f9
push id37529
push userncsoregi@mozilla.com
push dateMon, 22 Jun 2020 15:48:48 +0000
treeherdermozilla-central@fa015682f653 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1646933
milestone79.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 1646933 - DelayedStartInputStream::AsyncWait is wrongly implemented, r=smaug Differential Revision: https://phabricator.services.mozilla.com/D80342
ipc/glue/IPCStreamDestination.cpp
--- a/ipc/glue/IPCStreamDestination.cpp
+++ b/ipc/glue/IPCStreamDestination.cpp
@@ -22,16 +22,17 @@ namespace ipc {
 // IPCStreamDestination::DelayedStartInputStream
 //
 // When AutoIPCStream is used with delayedStart, we need to ask for data at the
 // first real use of the nsIInputStream. In order to do so, we wrap the
 // nsIInputStream, created by the nsIPipe, with this wrapper.
 
 class IPCStreamDestination::DelayedStartInputStream final
     : public nsIAsyncInputStream,
+      public nsIInputStreamCallback,
       public nsISearchableInputStream,
       public nsICloneableInputStream,
       public nsIBufferedInputStream {
  public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   DelayedStartInputStream(IPCStreamDestination* aDestination,
                           nsCOMPtr<nsIAsyncInputStream>&& aStream)
@@ -86,18 +87,29 @@ class IPCStreamDestination::DelayedStart
   CloseWithStatus(nsresult aReason) override {
     MaybeCloseDestination();
     return mStream->CloseWithStatus(aReason);
   }
 
   NS_IMETHOD
   AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
             uint32_t aRequestedCount, nsIEventTarget* aTarget) override {
-    MaybeStartReading();
-    return mStream->AsyncWait(aCallback, aFlags, aRequestedCount, aTarget);
+    {
+      MutexAutoLock lock(mMutex);
+      if (mAsyncWaitCallback && aCallback) {
+        return NS_ERROR_FAILURE;
+      }
+
+      mAsyncWaitCallback = aCallback;
+
+      MaybeStartReading(lock);
+    }
+
+    nsCOMPtr<nsIInputStreamCallback> callback = aCallback ? this : nullptr;
+    return mStream->AsyncWait(callback, aFlags, aRequestedCount, aTarget);
   }
 
   NS_IMETHOD
   Search(const char* aForString, bool aIgnoreCase, bool* aFound,
          uint32_t* aOffsetSearchedTo) override {
     MaybeStartReading();
     nsCOMPtr<nsISearchableInputStream> searchable = do_QueryInterface(mStream);
     MOZ_ASSERT(searchable);
@@ -133,26 +145,50 @@ class IPCStreamDestination::DelayedStart
     return stream->Init(aStream, aBufferSize);
   }
 
   NS_IMETHODIMP
   GetData(nsIInputStream** aResult) override {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
+  // nsIInputStreamCallback
+
+  NS_IMETHOD
+  OnInputStreamReady(nsIAsyncInputStream* aStream) override {
+    nsCOMPtr<nsIInputStreamCallback> callback;
+
+    {
+      MutexAutoLock lock(mMutex);
+
+      // We have been canceled in the meanwhile.
+      if (!mAsyncWaitCallback) {
+        return NS_OK;
+      }
+
+      callback.swap(mAsyncWaitCallback);
+    }
+
+    callback->OnInputStreamReady(this);
+    return NS_OK;
+  }
+
   void MaybeStartReading();
+  void MaybeStartReading(const MutexAutoLock& aProofOfLook);
 
   void MaybeCloseDestination();
 
  private:
   ~DelayedStartInputStream() = default;
 
   IPCStreamDestination* mDestination;
   nsCOMPtr<nsIAsyncInputStream> mStream;
 
+  nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback;
+
   // This protects mDestination: any method can be called by any thread.
   Mutex mMutex;
 
   class HelperRunnable;
 };
 
 class IPCStreamDestination::DelayedStartInputStream::HelperRunnable final
     : public Runnable {
@@ -190,16 +226,21 @@ class IPCStreamDestination::DelayedStart
  private:
   RefPtr<IPCStreamDestination::DelayedStartInputStream>
       mDelayedStartInputStream;
   Op mOp;
 };
 
 void IPCStreamDestination::DelayedStartInputStream::MaybeStartReading() {
   MutexAutoLock lock(mMutex);
+  MaybeStartReading(lock);
+}
+
+void IPCStreamDestination::DelayedStartInputStream::MaybeStartReading(
+    const MutexAutoLock& aProofOfLook) {
   if (!mDestination) {
     return;
   }
 
   if (mDestination->IsOnOwningThread()) {
     mDestination->StartReading();
     mDestination = nullptr;
     return;
@@ -227,16 +268,17 @@ void IPCStreamDestination::DelayedStartI
   mDestination->DispatchRunnable(runnable.forget());
 }
 
 NS_IMPL_ADDREF(IPCStreamDestination::DelayedStartInputStream);
 NS_IMPL_RELEASE(IPCStreamDestination::DelayedStartInputStream);
 
 NS_INTERFACE_MAP_BEGIN(IPCStreamDestination::DelayedStartInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream)
+  NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
   NS_INTERFACE_MAP_ENTRY(nsISearchableInputStream)
   NS_INTERFACE_MAP_ENTRY(nsICloneableInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIBufferedInputStream)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIInputStream, nsIAsyncInputStream)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAsyncInputStream)
 NS_INTERFACE_MAP_END
 
 // ----------------------------------------------------------------------------