Bug 1769878, ensure objects owned by the worker thread are cleared when the worker is shutting down, r=asuth,aosmond

Depends on D147858

Differential Revision: https://phabricator.services.mozilla.com/D149693
This commit is contained in:
Olli Pettay 2022-06-22 14:06:31 +00:00
Родитель f6d26b044a
Коммит e90bd7f443
5 изменённых файлов: 51 добавлений и 4 удалений

Просмотреть файл

@ -125,6 +125,11 @@ class EncodingCompleteEvent final : public DiscardableRunnable {
return mCreationEventTarget;
}
bool CanBeDeletedOnAnyThread() {
return !mEncodeCompleteCallback ||
mEncodeCompleteCallback->CanBeDeletedOnAnyThread();
}
private:
uint64_t mImgSize;
nsAutoString mType;
@ -192,8 +197,10 @@ class EncodingRunnable : public Runnable {
rv = mEncodingCompleteEvent->GetCreationThreadEventTarget()->Dispatch(
mEncodingCompleteEvent, nsIThread::DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
// Better to leak than to crash.
Unused << mEncodingCompleteEvent.forget();
if (!mEncodingCompleteEvent->CanBeDeletedOnAnyThread()) {
// Better to leak than to crash.
Unused << mEncodingCompleteEvent.forget();
}
return rv;
}

Просмотреть файл

@ -111,6 +111,11 @@ class EncodeCompleteCallback {
MOZ_CAN_RUN_SCRIPT
virtual nsresult ReceiveBlobImpl(already_AddRefed<BlobImpl> aBlobImpl) = 0;
// CanBeDeletedOnAnyThread is pure virtual, so that whoever extends this class
// needs to think how to handle cases like the owning DOM worker thread
// shutting down.
virtual bool CanBeDeletedOnAnyThread() = 0;
protected:
virtual ~EncodeCompleteCallback() = default;
};

Просмотреть файл

@ -39,6 +39,8 @@ void CanvasRenderingContextHelper::ToBlob(
// This is called on main thread.
MOZ_CAN_RUN_SCRIPT
nsresult ReceiveBlobImpl(already_AddRefed<BlobImpl> aBlobImpl) override {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<BlobImpl> blobImpl = aBlobImpl;
RefPtr<Blob> blob;
@ -58,6 +60,11 @@ void CanvasRenderingContextHelper::ToBlob(
return rv.StealNSResult();
}
bool CanBeDeletedOnAnyThread() override {
// EncodeCallback is used from the main thread only.
return false;
}
nsCOMPtr<nsIGlobalObject> mGlobal;
RefPtr<BlobCallback> mBlobCallback;
};

Просмотреть файл

@ -6,12 +6,14 @@
#include "OffscreenCanvas.h"
#include "mozilla/Atomics.h"
#include "mozilla/dom/BlobImpl.h"
#include "mozilla/dom/OffscreenCanvasBinding.h"
#include "mozilla/dom/OffscreenCanvasDisplayHelper.h"
#include "mozilla/dom/OffscreenCanvasRenderingContext2D.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRef.h"
#include "mozilla/dom/WorkerScope.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/Telemetry.h"
@ -277,11 +279,21 @@ OffscreenCanvas::CreateEncodeCompleteCallback(Promise* aPromise) {
// Encoder callback when encoding is complete.
class EncodeCallback : public EncodeCompleteCallback {
public:
explicit EncodeCallback(Promise* aPromise) : mPromise(aPromise) {}
explicit EncodeCallback(Promise* aPromise)
: mPromise(aPromise), mCanceled(false) {
WorkerPrivate* wp = GetCurrentThreadWorkerPrivate();
if (wp) {
mWorkerRef = WeakWorkerRef::Create(
wp, [self = RefPtr{this}]() { self->Cancel(); });
if (!mWorkerRef) {
Cancel();
}
}
}
// This is called on main thread.
nsresult ReceiveBlobImpl(already_AddRefed<BlobImpl> aBlobImpl) override {
RefPtr<BlobImpl> blobImpl = aBlobImpl;
mWorkerRef = nullptr;
if (mPromise) {
RefPtr<nsIGlobalObject> global = mPromise->GetGlobalObject();
@ -302,7 +314,17 @@ OffscreenCanvas::CreateEncodeCompleteCallback(Promise* aPromise) {
return NS_OK;
}
bool CanBeDeletedOnAnyThread() override { return mCanceled; }
void Cancel() {
mPromise = nullptr;
mWorkerRef = nullptr;
mCanceled = true;
}
RefPtr<Promise> mPromise;
RefPtr<WeakWorkerRef> mWorkerRef;
Atomic<bool> mCanceled;
};
return MakeAndAddRef<EncodeCallback>(aPromise);

Просмотреть файл

@ -110,8 +110,14 @@ void CaptureTask::NotifyRealtimeTrackData(MediaTrackGraph* aGraph,
public:
explicit EncodeComplete(CaptureTask* aTask) : mTask(aTask) {}
bool CanBeDeletedOnAnyThread() override {
// EncodeComplete is used from the main thread only.
return false;
}
nsresult ReceiveBlobImpl(
already_AddRefed<dom::BlobImpl> aBlobImpl) override {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<dom::BlobImpl> blobImpl(aBlobImpl);
mTask->TaskComplete(blobImpl.forget(), NS_OK);
mTask = nullptr;