Compare commits

...

1 Commits

Author SHA1 Message Date
James Hush
1b28fc8e8e Fix: Ensure EndFrame propagates through AIService before stop()
This fix addresses a critical bug where EndFrame (and potentially other
system frames) would trigger the stop() method in AIService but never
be pushed downstream to subsequent processors, causing pipelines to hang.

The issue occurred because AIService.process_frame() would call stop(frame)
for EndFrame without first pushing it downstream. This meant that downstream
processors never received the shutdown signal, leaving the pipeline in a
waiting state.

The fix ensures EndFrame is pushed downstream BEFORE calling stop(), following
the same pattern used by RTVIProcessor and properly-implemented processors.
This guarantees that:
1. Downstream processors receive the EndFrame for proper cleanup
2. The stop() method can then safely perform service-specific cleanup
3. The ordering prevents race conditions during shutdown

This bug affected all AI services inheriting from AIService that didn't
override process_frame() to explicitly handle EndFrame, including scenarios
with TTS services, LLM services, and other AI service implementations.

Fixes pipeline hangs during graceful shutdown when EndFrame is sent.
2025-11-17 11:09:42 +01:00

View File

@@ -152,6 +152,9 @@ class AIService(FrameProcessor):
elif isinstance(frame, CancelFrame):
await self.cancel(frame)
elif isinstance(frame, EndFrame):
# Push EndFrame before stop(), because stop() may wait on tasks to
# finish and downstream processors need to receive the EndFrame.
await self.push_frame(frame, direction)
await self.stop(frame)
async def process_generator(self, generator: AsyncGenerator[Frame | None, None]):