fix(ap): cancel the flows a fork draws from before its parks - #7
Merged
Merged
Conversation
Cancelling an ap cancelled its pending parks first and its forked flows second. Cancelling a park can resume the branch synchronously on the owner fiber: the branch fails at its `?` and pumps, the pump pulls the next value from a flow that is still live and forks again, the new park is cancelled on arrival, and control never reaches the loop that would have cancelled the flow. Over an infinite seed the process spun forever inside `cancel` at full CPU and the consumer never settled; over a finite seed it drained the whole seed before stopping. Found through samizdat's supervisor stream, a reduce over (ap (let [_ (?> (seed (repeat nil)))] (? (sleep ms)) (drain))): stopping it measured 88,641 iterations in the two seconds after the cancel. Cancel the flows first, then the parks, as Ambiguous.java cancels its choice ring before its token. With the flow cancelled, the next pull terminates the choice and the pump runs dry. Pinned by ebb.ap-cancel-seed-test: the cancel reaches the seed, no further fork runs, and the reduce settles with Cancelled.
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.
Cancelling an
apcancelled its pending parks first and its forked flows second. Cancelling a park can resume the branch synchronously on the owner fiber: the branch fails at its?and pumps, the pump pulls the next value from a flow that is still live and forks again, the new park is cancelled on arrival, and control never reaches the loop that would have cancelled the flow.Over an infinite seed the process spun forever inside
cancelat full CPU and the consumer never settled; over a finite seed it drained the whole seed before stopping.Found through samizdat's supervisor stream, a reduce over
(ap (let [_ (?> (seed (repeat nil)))] (? (sleep ms)) (drain))): stopping it measured 88,641 iterations in the two seconds after the cancel, with the reduce never settling.Fix: cancel the flows first, then the parks, as
Ambiguous.javacancels its choice ring before its token. With the flow cancelled the next pull terminates the choice and the pump runs dry.Pinned by
ebb.ap-cancel-seed-test: the cancel reaches the seed, no further fork runs, and the reduce settles with Cancelled. Full suite: 285 tests, 1207 assertions, 0 failures.