task core: port wait_until's pending-cancel wakeup; clear Thread.cancellable on resume (review, closes #250) - #302
Merged
Conversation
…ellable on resume Adversarial correctness review of the task core against definitions.py. `Thread.waitUntil` parked on the raw `readyFunc` and checked `deliverPendingCancel` only BEFORE blocking. The reference (`Thread.wait_until` 361-373) parks on `ready_func() or (cancellable() and has_pending_cancel())` and re-runs `deliver_pending_cancel` AFTER the block. The gap bites when a cancel arrives while the task is not cancellable — a sibling activation of the instance holds the exclusive slot, so `Task.requestCancellation` parks the request as `pending-cancel`. When the slot frees, the reference wakes the parked callback task and hands it TASK_CANCELLED; ours left the WAIT arm parked until some unrelated event landed on its set (possibly never: the canceller got BLOCKED and waits for a SUBTASK event that never comes), delivered a spurious NONE on the YIELD arm, and reordered a pending event ahead of TASK_CANCELLED. The reference's `cancellable` is a live predicate (`lock_available` in the callback loop, 2167/2175); ours is a static flag per block point, so the "lock is free" conjunct is supplied by the new `Task.implicitThreadCancellable()`, which also replaces the inline `excludeImplicit` expression in `requestCancellation`. `Thread.cancellable` stayed stale-true while the thread ran, so a `requestCancellation` reaching a RUNNING implicit thread (a nested same- instance task cancelling a handle whose callee is on the stack) picked it and hit `Thread.resume`'s assertion instead of parking as pending-cancel. Cleared on resume; re-set by the next block request. This is CM#707 item 2(c) of #250 — "deliver when the callee's exclusive lock frees, even if the parked task's waitable set never fires". `async/cancel-and-exclusive-lock.wast:196` now passes; its xfail (the last of class `cm707-cancel`) is removed. Regression: wait_until_pending_cancel_test.ts (three arms), stale_cancellable_flag_test.ts. Conformance 0 failed / 0 stale; sched-seeds green. Closes #250.
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.
Adversarial correctness review of
main@ 396a216, task-core track. One HIGH and one LOW finding inThread/Task, pinned by regression tests that fail on the pre-fix tree.F1 (HIGH) — lost wakeup in
Thread.waitUntil. The reference (Thread.wait_until, definitions.py 361-373) parks onready_func() or (cancellable() and has_pending_cancel())and re-runsdeliver_pending_cancelAFTER the block. Ours parked on the rawreadyFuncand checked only before. When a cancel arrives while a sibling holds the instance's exclusive slot (request parks aspending-cancel), the reference wakes the parked callback task on slot release and delivers TASK_CANCELLED; ours left the WAIT arm parked until an unrelated event (possibly forever — the canceller got BLOCKED and waits for a SUBTASK event that never comes), returned a spurious NONE on the YIELD arm, and delivered a pending event ahead of TASK_CANCELLED.wait_until_pending_cancel_test.tspins all three arms.This is CM#707 item 2(c) of #250.
async/cancel-and-exclusive-lock.wast:196now passes; its xfail — the last of classcm707-cancel— is removed, and the eight engine-lane expectation files and the README total move 1284→1285 passed / 127→126 xfail.F2 (LOW) — stale
Thread.cancellable. Stayed true while the thread ran, so arequestCancellationreaching a RUNNING implicit thread hitThread.resume's assertion instead of parking as pending-cancel. Cleared on resume.stale_cancellable_flag_test.ts.Gates:
just test-runtimegreen;just conformance0 failed / 0 stale;just sched-seedsgreen; all six browser lanes and three shell lanes match the updated expectations; fulljust gatesgreen on the union of the five review PRs.Closes #250. Follow-up for the JSPI
SuspensionPointtwin of this path: #300.Automerge armed.