This is an automated email from the git hooks/post-receive script.
pierov pushed a commit to branch geckoview-99.0.1-11.0-1 in repository tor-browser.
commit 7227342df73049980dd7c5a68e04a3b2928029b8 Author: Barret Rennie barret@brennie.ca AuthorDate: Tue Feb 1 03:23:44 2022 +0000
Bug 1743671 - Keep worker threads alive while IOUtils tasks are running r=Gijs,asuth a=RyanVM
Differential Revision: https://phabricator.services.mozilla.com/D137465 --- dom/system/IOUtils.cpp | 38 ++++++++++++++++++++++++++++++++------ dom/system/IOUtils.h | 18 ++++++++++++++++++ 2 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/dom/system/IOUtils.cpp b/dom/system/IOUtils.cpp index 0de583060a92f..3f3db833f03ba 100644 --- a/dom/system/IOUtils.cpp +++ b/dom/system/IOUtils.cpp @@ -32,6 +32,8 @@ #include "mozilla/Utf8.h" #include "mozilla/dom/IOUtilsBinding.h" #include "mozilla/dom/Promise.h" +#include "mozilla/dom/WorkerCommon.h" +#include "mozilla/dom/WorkerRef.h" #include "PathUtils.h" #include "nsCOMPtr.h" #include "nsError.h" @@ -290,13 +292,21 @@ already_AddRefed<Promise> IOUtils::WithPromiseAndState(GlobalObject& aGlobal, template <typename OkT, typename Fn> void IOUtils::DispatchAndResolve(IOUtils::EventQueue* aQueue, Promise* aPromise, Fn aFunc) { + RefPtr<StrongWorkerRef> workerRef; + if (!NS_IsMainThread()) { + // We need to manually keep the worker alive until the promise returned by + // Dispatch() resolves or rejects. + workerRef = StrongWorkerRef::CreateForcibly(GetCurrentThreadWorkerPrivate(), + __func__); + } + if (RefPtr<IOPromise<OkT>> p = aQueue->Dispatch<OkT, Fn>(std::move(aFunc))) { p->Then( GetCurrentSerialEventTarget(), __func__, - [promise = RefPtr(aPromise)](OkT&& ok) { + [workerRef, promise = RefPtr(aPromise)](OkT&& ok) { ResolveJSPromise(promise, std::forward<OkT>(ok)); }, - [promise = RefPtr(aPromise)](const IOError& err) { + [workerRef, promise = RefPtr(aPromise)](const IOError& err) { RejectJSPromise(promise, err); }); } @@ -393,6 +403,14 @@ already_AddRefed<Promise> IOUtils::ReadJSON(GlobalObject& aGlobal, nsCOMPtr<nsIFile> file = new nsLocalFile(); REJECT_IF_INIT_PATH_FAILED(file, aPath, promise);
+ RefPtr<StrongWorkerRef> workerRef; + if (!NS_IsMainThread()) { + // We need to manually keep the worker alive until the promise returned by + // Dispatch() resolves or rejects. + workerRef = StrongWorkerRef::CreateForcibly( + GetCurrentThreadWorkerPrivate(), __func__); + } + state->mEventQueue ->template Dispatch<JsBuffer>( [file, decompress = aOptions.mDecompress]() { @@ -400,7 +418,7 @@ already_AddRefed<Promise> IOUtils::ReadJSON(GlobalObject& aGlobal, }) ->Then( GetCurrentSerialEventTarget(), __func__, - [promise = RefPtr{promise}, file](JsBuffer&& aBuffer) { + [workerRef, promise = RefPtr{promise}, file](JsBuffer&& aBuffer) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(promise->GetGlobalObject()))) { promise->MaybeRejectWithUnknownError( @@ -437,7 +455,7 @@ already_AddRefed<Promise> IOUtils::ReadJSON(GlobalObject& aGlobal,
promise->MaybeResolve(val); }, - [promise = RefPtr{promise}](const IOError& aErr) { + [workerRef, promise = RefPtr{promise}](const IOError& aErr) { RejectJSPromise(promise, aErr); }); }); @@ -721,13 +739,21 @@ already_AddRefed<Promise> IOUtils::GetWindowsAttributes( nsCOMPtr<nsIFile> file = new nsLocalFile(); REJECT_IF_INIT_PATH_FAILED(file, aPath, promise);
+ RefPtr<StrongWorkerRef> workerRef; + if (!NS_IsMainThread()) { + // We need to manually keep the worker alive until the promise returned by + // Dispatch() resolves or rejects. + workerRef = StrongWorkerRef::CreateForcibly( + GetCurrentThreadWorkerPrivate(), __func__); + } + state->mEventQueue ->template Dispatch<uint32_t>([file = std::move(file)]() { return GetWindowsAttributesSync(file); }) ->Then( GetCurrentSerialEventTarget(), __func__, - [promise = RefPtr{promise}](const uint32_t aAttrs) { + [workerRef, promise = RefPtr{promise}](const uint32_t aAttrs) { WindowsFileAttributes attrs;
attrs.mReadOnly.Construct(aAttrs & FILE_ATTRIBUTE_READONLY); @@ -736,7 +762,7 @@ already_AddRefed<Promise> IOUtils::GetWindowsAttributes(
promise->MaybeResolve(attrs); }, - [promise = RefPtr{promise}](const IOError& aErr) { + [workerRef, promise = RefPtr{promise}](const IOError& aErr) { RejectJSPromise(promise, aErr); }); }); diff --git a/dom/system/IOUtils.h b/dom/system/IOUtils.h index ef5d84e00c00f..064fb9467f48f 100644 --- a/dom/system/IOUtils.h +++ b/dom/system/IOUtils.h @@ -189,6 +189,9 @@ class IOUtils final { * Dispatch a task on the event queue and resolve or reject the associated * promise based on the result. * + * NB: If the calling thread is a worker, this function takes care of keepting + * it alive until the |IOPromise| can complete. + * * @param aPromise The promise corresponding to the task running on the event * queue. * @param aFunc The task to run. @@ -486,6 +489,21 @@ class IOUtils::EventQueue final { EventQueue& operator=(const EventQueue&) = delete; EventQueue& operator=(EventQueue&&) = delete;
+ /** + * Dispatch a task on the event queue. + * + * NB: If using this directly from |IOUtils| instead of + * |IOUtils::DispatchAndResolve| *and* the calling thread is a worker, you + * *must* take care to keep the worker thread alive until the |IOPromise| + * resolves or rejects. See the implementation of + * |IOUtils::DispatchAndResolve| or |IOUtils::GetWindowsAttributes| for an + * example. + * + * @param aFunc The task to dispatch on the event queue. + * + * @return A promise that resolves to the task's return value or rejects with + * an error. + */ template <typename OkT, typename Fn> RefPtr<IOPromise<OkT>> Dispatch(Fn aFunc);