Skip to content

[Proxying] Cancel proxied work when the worker thread dies - #18741

Merged
tlively merged 1 commit into
mainfrom
proxying-shutdown
Mar 1, 2023
Merged

[Proxying] Cancel proxied work when the worker thread dies#18741
tlively merged 1 commit into
mainfrom
proxying-shutdown

Conversation

@tlively

@tlively tlively commented Feb 14, 2023

Copy link
Copy Markdown
Member

Update the synchronous proxying APIs to return 0 when attempting to proxy to a
thread that has already exited or has been canceled or exits or is canceled
before the proxied work is completed.

To implement cancellation, add an optional cancel function pointer to the
tasks queued in em_task_queues, which are the internal thread-specific queues
used in the implementation of em_proxying_queue. This cancel function
pointer is not controllable directly by users of the API, but is rather used
internally to ensure that synchronous waiters are notified when the thread they
are waiting on dies. This mechanism will scale to other forms of cancellation
notification in the future. For example, it could be used to reject a promise
associated with the proxied work.

When a thread dies, it runs the cancellation handlers for each task in its
mailbox. Those tasks each carry a pointer to some task queue owned by a proxying
queue, so their cancellation handlers in turn run the cancellation handlers for
all the tasks in those pointed-to queues.

Task queue cancellation handlers do not handle the case of proxied work that has
been started but not finished when the worker thread dies because that work has
already been removed from the task queues. To cancel in-progress work as well,
update the implementation of synchronous proxying to place em_proxying_ctx
objects associated with active work in a thread-local doubly linked list that is
traversed by a registered thread specific data destructor. The destructor takes
care of canceling the active work.

Implements the design sketched out in #18631.

@tlively
tlively requested review from kripken and sbc100 February 14, 2023 01:49
@tlively

tlively commented Feb 14, 2023

Copy link
Copy Markdown
Member Author

The failing wasm2js test should be fixed by WebAssembly/binaryen#5489.

@sbc100 sbc100 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do for each task we proxy we actually now create two tasks? (i.e. the user's work in the queue they specify, and then a special notification task which lives in the mailbox of the target thread?)

Comment thread system/lib/pthread/proxying.c
Comment thread test/pthread/test_pthread_proxying.c
Comment thread test/test_core.py
@tlively

tlively commented Feb 17, 2023

Copy link
Copy Markdown
Member Author

Do for each task we proxy we actually now create two tasks? (i.e. the user's work in the queue they specify, and then a special notification task which lives in the mailbox of the target thread?)

In the worst case, yes. However, if there is already a pending notification task in the mailbox of the target thread, then we don't create another one of those.

@sbc100 sbc100 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't say I've read an understood the entire change, especially the different tests cases. But I think this is great direction and the test coverage looks thorough.

@tlively

tlively commented Feb 17, 2023

Copy link
Copy Markdown
Member Author

Is test_pthread_dlopen_many flaky before this change or because of this change?

@sbc100

sbc100 commented Feb 17, 2023

Copy link
Copy Markdown
Collaborator

I think the test failure on wasm64 is new flake that I recently added.

@sbc100

sbc100 commented Feb 17, 2023

Copy link
Copy Markdown
Collaborator

Is test_pthread_dlopen_many flaky before this change or because of this change?

yes, but I think/hope its only flaky on wasm64

@tlively

tlively commented Feb 17, 2023

Copy link
Copy Markdown
Member Author

That same test was failing asan tests with a detected memory leak earlier in this PR, so it's not just a wasm64 flake: https://app.circleci.com/pipelines/github/emscripten-core/emscripten/25923/workflows/3092d7a9-0f07-465c-8972-c2b364ac6d5d/jobs/604201

@tlively
tlively changed the base branch from main to proxying-mailbox February 25, 2023 05:27
@tlively
tlively force-pushed the proxying-shutdown branch 2 times, most recently from 5223090 to e0abb19 Compare February 27, 2023 15:35
@tlively
tlively force-pushed the proxying-mailbox branch from 2f288d3 to bc9b5ad Compare March 1, 2023 01:09
@tlively
tlively force-pushed the proxying-shutdown branch from e0abb19 to 09a3df8 Compare March 1, 2023 01:09
Base automatically changed from proxying-mailbox to main March 1, 2023 16:30
@tlively
tlively force-pushed the proxying-shutdown branch from 09a3df8 to 8b4eb90 Compare March 1, 2023 16:38
@sbc100

sbc100 commented Mar 1, 2023

Copy link
Copy Markdown
Collaborator

Is this change good to go now?

@tlively

tlively commented Mar 1, 2023

Copy link
Copy Markdown
Member Author

Yes. Since it got smaller since you last approved it, I was just going to land it as soon as the tests pass.

@tlively

tlively commented Mar 1, 2023

Copy link
Copy Markdown
Member Author

Is it safe to land despite the test_minimal_runtime_code_size_random_printf_wasm failure?

@sbc100

sbc100 commented Mar 1, 2023

Copy link
Copy Markdown
Collaborator

I just pushed a rebase of the expectations. If you rebase again you should be good.

Update the synchronous proxying APIs to return 0 when attempting to proxy to a
thread that has already exited or has been canceled or exits or is canceled
before the proxied work is completed.

To implement cancellation, add an optional `cancel` function pointer to the
tasks queued in `em_task_queue`s, which are the internal thread-specific queues
used in the implementation of `em_proxying_queue`. This `cancel` function
pointer is not controllable directly by users of the API, but is rather used
internally to ensure that synchronous waiters are notified when the thread they
are waiting on dies. This mechanism will scale to other forms of cancellation
notification in the future. For example, it could be used to reject a promise
associated with the proxied work.

When a thread dies, it runs the cancellation handlers for each task in its
mailbox. Those tasks each carry a pointer to some task queue owned by a proxying
queue, so their cancellation handlers in turn run the cancellation handlers for
all the tasks in those pointed-to queues.

Task queue cancellation handlers do not handle the case of proxied work that has
been started but not finished when the worker thread dies because that work has
already been removed from the task queues. To cancel in-progress work as well,
update the implementation of synchronous proxying to place `em_proxying_ctx`
objects associated with active work in a thread-local doubly linked list that is
traversed by a registered thread specific data destructor. The destructor takes
care of canceling the active work.

Implements the design sketched out in #18631.
@tlively
tlively force-pushed the proxying-shutdown branch from 8b4eb90 to ea71ab3 Compare March 1, 2023 19:37
@tlively
tlively merged commit 168dafb into main Mar 1, 2023
@tlively
tlively deleted the proxying-shutdown branch March 1, 2023 21:04
impact-maker pushed a commit to impact-maker/emscripten that referenced this pull request Mar 17, 2023
…n-core#18741)

Update the synchronous proxying APIs to return 0 when attempting to proxy to a
thread that has already exited or has been canceled or exits or is canceled
before the proxied work is completed.

To implement cancellation, add an optional `cancel` function pointer to the
tasks queued in `em_task_queue`s, which are the internal thread-specific queues
used in the implementation of `em_proxying_queue`. This `cancel` function
pointer is not controllable directly by users of the API, but is rather used
internally to ensure that synchronous waiters are notified when the thread they
are waiting on dies. This mechanism will scale to other forms of cancellation
notification in the future. For example, it could be used to reject a promise
associated with the proxied work.

When a thread dies, it runs the cancellation handlers for each task in its
mailbox. Those tasks each carry a pointer to some task queue owned by a proxying
queue, so their cancellation handlers in turn run the cancellation handlers for
all the tasks in those pointed-to queues.

Task queue cancellation handlers do not handle the case of proxied work that has
been started but not finished when the worker thread dies because that work has
already been removed from the task queues. To cancel in-progress work as well,
update the implementation of synchronous proxying to place `em_proxying_ctx`
objects associated with active work in a thread-local doubly linked list that is
traversed by a registered thread specific data destructor. The destructor takes
care of canceling the active work.

Implements the design sketched out in emscripten-core#18631.
impact-maker pushed a commit to impact-maker/emscripten that referenced this pull request Mar 17, 2023
…n-core#18741)

Update the synchronous proxying APIs to return 0 when attempting to proxy to a
thread that has already exited or has been canceled or exits or is canceled
before the proxied work is completed.

To implement cancellation, add an optional `cancel` function pointer to the
tasks queued in `em_task_queue`s, which are the internal thread-specific queues
used in the implementation of `em_proxying_queue`. This `cancel` function
pointer is not controllable directly by users of the API, but is rather used
internally to ensure that synchronous waiters are notified when the thread they
are waiting on dies. This mechanism will scale to other forms of cancellation
notification in the future. For example, it could be used to reject a promise
associated with the proxied work.

When a thread dies, it runs the cancellation handlers for each task in its
mailbox. Those tasks each carry a pointer to some task queue owned by a proxying
queue, so their cancellation handlers in turn run the cancellation handlers for
all the tasks in those pointed-to queues.

Task queue cancellation handlers do not handle the case of proxied work that has
been started but not finished when the worker thread dies because that work has
already been removed from the task queues. To cancel in-progress work as well,
update the implementation of synchronous proxying to place `em_proxying_ctx`
objects associated with active work in a thread-local doubly linked list that is
traversed by a registered thread specific data destructor. The destructor takes
care of canceling the active work.

Implements the design sketched out in emscripten-core#18631.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants