fix(voice): shield transcript rotation from cancellation - #7300
DeepanshuPal wants to merge 1 commit into
Conversation
|
|
| # just in case, we do log a warning if it does) | ||
| while not self._rotate_segment_atask.done(): | ||
| await self._rotate_segment_atask | ||
| await asyncio.shield(self._rotate_segment_atask) |
There was a problem hiding this comment.
🟡 Cancelled shutdown leaks synchronizer tasks
Cancelling aclose() during rotation leaves the shielded task running after shutdown exits. _rotate_segment_task creates a new implementation whose background tasks remain open.
Learn more
aclose() marks the synchronizer closed and then waits at this barrier. Cancellation now exits aclose() without cancelling the rotation. The surviving rotation closes the old implementation, then _rotate_segment_task unconditionally constructs a new implementation with three background tasks. Since the synchronizer is already closed and aclose() has exited, nothing closes that new implementation.
Example: A session starts rotating a transcript segment and then shutdown calls aclose(). If shutdown cancellation arrives before rotation finishes, aclose() exits while rotation continues. Rotation creates a fresh closed-session implementation, leaving its main, capture, and speaking-rate tasks alive.
Recommended fix: Make cancelled shutdown retain ownership of the protected rotation and close whichever implementation it creates. One option is a dedicated close task that awaits rotation and closes the final _impl, with aclose() shielding that task so later cleanup can still await it.
Was this helpful? React with 👍 or 👎 to provide feedback.
Fixes #7299.
TranscriptSynchronizer.barrier()awaits a session-owned rotation task. Cancelling any barrier waiter currently propagates into that shared task, leaving later barriers unable to complete. Shield the shared await so the caller remains cancellable without cancelling segment rotation.Added a focused regression that cancels one waiter, verifies the rotation task stays alive, releases it, then confirms a later barrier completes.
Tests:
python -m pytest tests/test_transcript_sync_cancellation.py -qruff check livekit-agents/livekit/agents/voice/transcription/synchronizer.py tests/test_transcript_sync_cancellation.pyruff format --check livekit-agents/livekit/agents/voice/transcription/synchronizer.py tests/test_transcript_sync_cancellation.py