Closed Bug 1345251 Opened 7 years ago Closed 7 years ago

MozPromise is not usable on worker threads

Categories

(Core :: XPCOM, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla55
Tracking Status
firefox55 --- fixed

People

(Reporter: bkelly, Assigned: bkelly)

References

Details

Attachments

(1 file, 3 obsolete files)

MozPromise needs to dispatch runnables at a thread target for Then(), etc.  Currently this cannot be done on Worker threads because the Worker thread target requires nsICancelableRunnable to be implemented.

Also, we should probably assert in the MozPromise runnables that the WorkerPrivate has a holder keeping the thread alive.  Otherwise MozPromise is pretty unsafe there.

I'd like to use MozPromise in the Clients API, so I need this for bug 1293277.
Please be careful with that:

Some asserts for "reliable dispatch" were recently removed (bug 1343337) because we got rid of FlushableTaskQueue's in media code (bug 1270039). These asserts were there because (I believe) MozPromise expects all dispatched tasks to always run to completion, unless the users explicitly Disconnect()'s them through the MozPromise interface.

So re-introducing disappearing tasks may be dangerous!

JW, you know much more about that aspect of MozPromise and task queues, what do you think?
Flags: needinfo?(jwwang)
My plan is to make the Cancel() method on MozPromise runnables just call Run().  That is what we do for things like IPC runnables which must be executed.
AbstractThread does its own wrapper runnable, though.  I need to make that cancelable as well.

Once again I am really frustrated we decided to make a second parallel thread ecosystem separate from nsIThread.
This patch solves the problems with a few changes:

1) Make all MozPromise nsICancelableRunnable objects.  They are implemented to always execute their Run(), so current invariants should not change.
2) Make AbstractThread's Runner implement nsICancelableRunnable interface.  It will attempt to proxy the Cancel() to its inner runnable.
3) Make the XPCOM wrapper avoid dispatching a non-cancelable runnable to set its TLS if its already on the target thread.
4) Make worker's RuntimeService create an AbstractThread at worker startup so AbstractThread::GetCurrent() functions.
Attachment #8844655 - Flags: review?(gsquelart)
Comment on attachment 8844655 [details] [diff] [review]
Make MozPromise usable on worker threads. r=gerald

Review of attachment 8844655 [details] [diff] [review]:
-----------------------------------------------------------------

Sorry.  Included some different files there.
Attachment #8844655 - Flags: review?(gsquelart)
Attachment #8844655 - Attachment is obsolete: true
And please request the review from :jwwang, he's the better expert for MozPromise & threads.
Will I get the right patch this time?
Attachment #8844657 - Attachment is obsolete: true
Comment on attachment 8844658 [details] [diff] [review]
Make MozPromise usable on worker threads. r=gerald

Please see comment 4 for the patch description.
Attachment #8844658 - Flags: review?(jwwang)
(In reply to Ben Kelly [not reviewing due to deadline][:bkelly] from comment #2)
> My plan is to make the Cancel() method on MozPromise runnables just call
> Run().  That is what we do for things like IPC runnables which must be
> executed.

Can you give some code examples? It is hard to me to think Cancel() means "To run" in the IPC context. Also I think Cancel() should mean "Not to run" in most cases.
(In reply to JW Wang [:jwwang] [:jw_wang] from comment #10)
> Can you give some code examples? It is hard to me to think Cancel() means
> "To run" in the IPC context. Also I think Cancel() should mean "Not to run"
> in most cases.

In most cases it does.  But my understanding is MozPromise is designed around the idea that once Dispatch() returns success then the runnable will always run.  The way this achieved on worker threads is to call Run() in Cancel().

Existing example:

https://dxr.mozilla.org/mozilla-central/source/ipc/glue/BackgroundImpl.cpp#1791
To clarify, I'm happy to ignore MozPromise runnables if they are canceled, but comment 1 suggested that was not advisable.  I don't have time to add some new cancelation facility to MozPromise, though.  I just need to be able to use MozPromise on worker threads safely and this seems the best approach at the moment.
Also, I'm open to other suggestions or patches.  This is blocking bug 1293277 which is in turn blocking multi-e10s which is a high priority at the moment.
(In reply to Ben Kelly [not reviewing due to deadline][:bkelly] from comment #11)
> In most cases it does.  But my understanding is MozPromise is designed
> around the idea that once Dispatch() returns success then the runnable will
> always run.

There are some noticeable details in the statement "once Dispatch() returns success then the runnable will always run".

http://searchfox.org/mozilla-central/rev/1bc7720a434af3c13b68b8d69f92078cae8890c4/xpcom/threads/MozPromise.h#422
The resolve/reject function will not be invoked when the ThenValue is disconnected even if Dispatch() has succeeded and the runnable is running on the target thread which in a sense means "Not to run" to a MozPromise client.

However, I think it should be fine to call Run() in Cancel() because we require the client to disconnect the ThenValue explicitly if it doesn't want resolve/reject function to be run.
Comment on attachment 8844658 [details] [diff] [review]
Make MozPromise usable on worker threads. r=gerald

Review of attachment 8844658 [details] [diff] [review]:
-----------------------------------------------------------------

::: xpcom/threads/AbstractThread.cpp
@@ +172,5 @@
>  
> +    nsresult Cancel() override
> +    {
> +      // Set the TLS during Cancel() just in case it calls Run().
> +      class MOZ_STACK_CLASS AutoTaskGuard final {

We have the same one in Run(). Please extract the common code.
Attachment #8844658 - Flags: review?(jwwang) → review+
Thank you for helping, JW.
Flags: needinfo?(jwwang)
Thanks for the review!

Update patch to share the AutoTaskGuard code between the two uses.

https://treeherder.mozilla.org/#/jobs?repo=try&revision=7c24503d01197364ee8b63edea4464ef0c251f28
Attachment #8844658 - Attachment is obsolete: true
Attachment #8844929 - Flags: review+
Pushed by bkelly@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/6f760f5997f1
Make MozPromise usable on worker threads. r=gerald
https://hg.mozilla.org/mozilla-central/rev/6f760f5997f1
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla55
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: