Skip to content

Fix pipelined engine reset(): cancel before drain#47

Merged
stikves merged 2 commits into
apple:mainfrom
stikves:sukru/fix-pipelined-drain-deadlock
Jun 15, 2026
Merged

Fix pipelined engine reset(): cancel before drain#47
stikves merged 2 commits into
apple:mainfrom
stikves:sukru/fix-pipelined-drain-deadlock

Conversation

@stikves

@stikves stikves commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

The producer task holds the engine lock until it finishes. If the consumer stops early (e.g. EOS detected), the producer may still be running. drain() waits for the lock to be released, but cancellation was only happening AFTER drain — creating a deadlock that triggers the 5-second fatalError timeout.

Fix: cancel the GenerationToken and Task before calling drain(). The producer checks isCancelled on its next loop iteration, releases the lock, and drain() can proceed.

Fixes #41

The producer task holds the engine lock until it finishes. If the
consumer stops early (e.g. EOS detected), the producer may still be
running. drain() waits for the lock to be released, but cancellation
was only happening AFTER drain — creating a deadlock that triggers
the 5-second fatalError timeout.

Fix: cancel the GenerationToken and Task before calling drain().
The producer checks isCancelled on its next loop iteration, releases
the lock, and drain() can proceed.

Fixes apple#41
@timokoethe

Copy link
Copy Markdown

Using the code snippet from #41 in an Xcode macOS application, I can confirm that these changes fix issue #41 on my side. Thank you!

@stikves stikves merged commit 9afe6d6 into apple:main Jun 15, 2026
3 checks passed
@stikves stikves deleted the sukru/fix-pipelined-drain-deadlock branch June 15, 2026 22:33
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.

CoreAIPipelinedEngine producer remains active after EOS, causing the next response to crash in drain()

3 participants