Bug 1416724 - part 2 - MutableBlobStorage should check the return value of TaskQueue::Dispatch(), r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 15 Nov 2017 07:58:03 +0100
changeset 391969 64c4030422704671d85e17092cb4de01dc6c0528
parent 391968 430e5be1f7bb6c2ebd991bc5e2a2222b83d2fdf2
child 391970 ddbbd455f0589af4de3d2046528e575d820e9e5b
push id32909
push usercbrindusan@mozilla.com
push dateWed, 15 Nov 2017 22:25:14 +0000
treeherdermozilla-central@f41930a869a8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1416724
milestone59.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 1416724 - part 2 - MutableBlobStorage should check the return value of TaskQueue::Dispatch(), r=smaug
dom/file/MutableBlobStorage.cpp
dom/file/MutableBlobStorage.h
--- a/dom/file/MutableBlobStorage.cpp
+++ b/dom/file/MutableBlobStorage.cpp
@@ -359,17 +359,17 @@ MutableBlobStorage::MutableBlobStorage(M
 }
 
 MutableBlobStorage::~MutableBlobStorage()
 {
   free(mData);
 
   if (mFD) {
     RefPtr<Runnable> runnable = new CloseFileRunnable(mFD);
-    DispatchToIOThread(runnable.forget());
+    Unused << DispatchToIOThread(runnable.forget());
   }
 
   if (mTaskQueue) {
     mTaskQueue->BeginShutdown();
   }
 
   if (mActor) {
     NS_ProxyRelease("MutableBlobStorage::mActor",
@@ -403,17 +403,20 @@ MutableBlobStorage::GetBlobWhenReady(nsI
     MOZ_ASSERT(mActor);
 
     // We want to wait until all the WriteRunnable are completed. The way we do
     // this is to go to the I/O thread and then we come back: the runnables are
     // executed in order and this LastRunnable will be... the last one.
     // This Runnable will also close the FD on the I/O thread.
     RefPtr<Runnable> runnable =
       new LastRunnable(this, aParent, aContentType, aCallback);
-    DispatchToIOThread(runnable.forget());
+
+    // If the dispatching fails, we are shutting down and it's fine to do not
+    // run the callback.
+    Unused << DispatchToIOThread(runnable.forget());
     return;
   }
 
   // If we are waiting for the temporary file, it's better to wait...
   if (previousState == eWaitingForTemporaryFile) {
     mPendingParent = aParent;
     mPendingContentType = aContentType;
     mPendingCallback = aCallback;
@@ -470,17 +473,20 @@ MutableBlobStorage::Append(const void* a
     }
 
     RefPtr<WriteRunnable> runnable =
       WriteRunnable::CopyBuffer(this, aData, aLength);
     if (NS_WARN_IF(!runnable)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    DispatchToIOThread(runnable.forget());
+    nsresult rv = DispatchToIOThread(runnable.forget());
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
 
     mDataLen += aLength;
     return NS_OK;
   }
 
   // By default, we store in memory.
 
   uint64_t offset = mDataLen;
@@ -576,17 +582,20 @@ MutableBlobStorage::TemporaryFileCreated
   MOZ_ASSERT_IF(mPendingCallback, mStorageState == eClosed);
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(aFD);
 
   // If the object has been already closed and we don't need to execute a
   // callback, we need just to close the file descriptor in the correct thread.
   if (mStorageState == eClosed && !mPendingCallback) {
     RefPtr<Runnable> runnable = new CloseFileRunnable(aFD);
-    DispatchToIOThread(runnable.forget());
+
+    // If this dispatching fails, CloseFileRunnable will close the FD in the
+    // DTOR on the current thread.
+    Unused << DispatchToIOThread(runnable.forget());
 
     // Let's inform the parent that we have nothing else to do.
     mActor->SendOperationDone(false, EmptyCString());
     mActor = nullptr;
     return;
   }
 
   // If we still receiving data, we can proceed in temporary-file mode.
@@ -600,30 +609,34 @@ MutableBlobStorage::TemporaryFileCreated
   // This runnable takes the ownership of mData and it will write this buffer
   // into the temporary file.
   RefPtr<WriteRunnable> runnable =
     WriteRunnable::AdoptBuffer(this, mData, mDataLen);
   MOZ_ASSERT(runnable);
 
   mData = nullptr;
 
-  DispatchToIOThread(runnable.forget());
+  nsresult rv = DispatchToIOThread(runnable.forget());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    // Shutting down, we cannot continue.
+    return;
+  }
 
   // If we are closed, it means that GetBlobWhenReady() has been called when we
   // were already waiting for a temporary file-descriptor. Finally we are here,
   // AdoptBuffer runnable is going to write the current buffer into this file.
   // After that, there is nothing else to write, and we dispatch LastRunnable
   // which ends up calling mPendingCallback via CreateBlobRunnable.
   if (mStorageState == eClosed) {
     MOZ_ASSERT(mPendingCallback);
 
     RefPtr<Runnable> runnable =
       new LastRunnable(this, mPendingParent, mPendingContentType,
                        mPendingCallback);
-    DispatchToIOThread(runnable.forget());
+    Unused << DispatchToIOThread(runnable.forget());
 
     mPendingParent = nullptr;
     mPendingCallback = nullptr;
   }
 }
 
 void
 MutableBlobStorage::AskForBlob(TemporaryIPCBlobChildCallback* aCallback,
@@ -646,29 +659,34 @@ MutableBlobStorage::ErrorPropagated(nsre
   mErrorResult = aRv;
 
   if (mActor) {
     mActor->SendOperationDone(false, EmptyCString());
     mActor = nullptr;
   }
 }
 
-void
+nsresult
 MutableBlobStorage::DispatchToIOThread(already_AddRefed<nsIRunnable> aRunnable)
 {
   if (!mTaskQueue) {
     nsCOMPtr<nsIEventTarget> target
       = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     MOZ_ASSERT(target);
 
     mTaskQueue = new TaskQueue(target.forget());
   }
 
   nsCOMPtr<nsIRunnable> runnable(aRunnable);
-  mTaskQueue->Dispatch(runnable.forget());
+  nsresult rv = mTaskQueue->Dispatch(runnable.forget());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
 }
 
 size_t
 MutableBlobStorage::SizeOfCurrentMemoryBuffer() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mStorageState < eInTemporaryFile ? mDataLen : 0;
 }
--- a/dom/file/MutableBlobStorage.h
+++ b/dom/file/MutableBlobStorage.h
@@ -84,17 +84,18 @@ private:
   ~MutableBlobStorage();
 
   bool ExpandBufferSize(uint64_t aSize);
 
   bool ShouldBeTemporaryStorage(uint64_t aSize) const;
 
   bool MaybeCreateTemporaryFile();
 
-  void DispatchToIOThread(already_AddRefed<nsIRunnable> aRunnable);
+  MOZ_MUST_USE nsresult
+  DispatchToIOThread(already_AddRefed<nsIRunnable> aRunnable);
 
   // All these variables are touched on the main thread only.
 
   void* mData;
   uint64_t mDataLen;
   uint64_t mDataBufferLen;
 
   enum StorageState {