Make ExitWaiter.doExit idempotent to avoid double-resuming continuations#1861
Open
radheradhe01 wants to merge 1 commit into
Open
Make ExitWaiter.doExit idempotent to avoid double-resuming continuations#1861radheradhe01 wants to merge 1 commit into
radheradhe01 wants to merge 1 commit into
Conversation
### Problem
`ExitWaiter.doExit` resumes every stored continuation but never guards against being called twice and never clears the array:
```swift
public func doExit(exitStatus: ExitStatus) {
for cc in continuations {
cc.resume(returning: exitStatus)
}
self.exitStatus = exitStatus
}
```
`doExit` can be reached more than once for the same process. In the exec path, the registered `onExit` callback calls `releaseWaiters` (→ `doExit`) and then performs further work that can throw (`process.delete()`); `ExitMonitor.track` catches that error and invokes the **same** `onExit` again, calling `doExit` a second time. Resuming a `CheckedContinuation` twice is a fatal trap.
### Fix
Make `doExit` idempotent: return early if the exit has already been recorded, set `exitStatus` first, and clear the continuations before resuming them so they cannot be resumed again.
### Notes
All access is serialized on the owning actor; the guard simply makes the "exit fires once" invariant explicit and crash-safe.
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.
Problem
ExitWaiter.doExitresumes every stored continuation but never guards against being called twice and never clears the array:doExitcan be reached more than once for the same process. In the exec path, the registeredonExitcallback callsreleaseWaiters(→doExit) and then performs further work that can throw (process.delete());ExitMonitor.trackcatches that error and invokes the sameonExitagain, callingdoExita second time. Resuming aCheckedContinuationtwice is a fatal trap.Fix
Make
doExitidempotent: return early if the exit has already been recorded, setexitStatusfirst, and clear the continuations before resuming them so they cannot be resumed again.Notes
All access is serialized on the owning actor; the guard simply makes the "exit fires once" invariant explicit and crash-safe.