Ensure cross-context promise settlements run under an IncomingRequest - #7004
Draft
jqmmes wants to merge 2 commits into
Draft
Ensure cross-context promise settlements run under an IncomingRequest#7004jqmmes wants to merge 2 commits into
jqmmes wants to merge 2 commits into
Conversation
Cross-context promise resolution queues actions on the target IoContext's DeleteQueue. Running an action settles a promise, which can run application JavaScript, which is in turn free to schedule another action on the same queue. Holding the queue's lock while running actions would therefore deadlock. Add takeActions(), which moves the queued actions out from under the lock and hands them to the caller to run after it is released. Make resetCrossThreadSignal() public so the queue's owner can re-arm the signal independently of draining, and cover both in io-own-test. Nothing calls takeActions() yet, so this is inert.
Contributor
|
APIError: Invalid Anthropic API Key |
2 similar comments
Contributor
|
APIError: Invalid Anthropic API Key |
Contributor
|
APIError: Invalid Anthropic API Key |
Contributor
|
@jqmmes Bonk workflow failed. Check the logs for details. View workflow run · To retry, trigger Bonk again. |
The delete queue signal task woke on a queued cross-context promise settlement and immediately called run() to execute it. run() reaches IoContext::now() while acquiring the actor's locks, and now() requires a current IncomingRequest. An actor's IoContext outlives its requests, so a settlement arriving while the actor sat idle -- holding hibernatable WebSockets, say -- failed the "the IoContext has no current IncomingRequest" requirement and aborted the IoContext, breaking every consumer of that actor. Settling a promise runs application JavaScript, which needs the metrics, tracing, timers, and IoChannelFactory that only an IncomingRequest supplies, so there is no correct way to run one without a request. Instead: - runImpl() drains the queue before delivering an event, so actions run under a request that is already fully formed. - The signal task asks scheduleCrossContextActionDrain() for a run, which returns none when no request could own one, leaving the actions queued for the actor's next event. Otherwise it registers the run as a wait-until task so the request cannot drain from under it. - The signal is re-armed before draining. Consuming a signal without installing a fresh one first left an action that arrived mid-drain queued with nothing outstanding to wake the context again, so it sat there until an unrelated action happened along. The handle_cross_request_promise_resolution flag guarantees that a promise settles in its owning IoContext, not that it settles promptly, so deferring to the next event keeps that contract. A deferred settlement does wait for the next event to arrive, which is a large improvement over aborting the actor outright. Cover settlement under an active request, under a draining request with waitUntil work outstanding, and on an idle actor where it must wait for the next event. Also drive the signal task directly, through the executor a promise's context tag hands out, to cover an action scheduled while a drain is already in progress.
jqmmes
force-pushed
the
joaquim/fix-io-context-run
branch
from
August 14, 2026 09:43
d91ae53 to
02ca769
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prevent an actor's delete-queue signal task from calling
IoContext::run()without a current
IncomingRequest.Cross-context promise actions now run under a live request. If the actor is
idle, they remain queued until its next real event creates an
IncomingRequest.