fix: prevent race condition in listener iteration - #1956
Conversation
Fixed RuntimeError when listeners list is modified during event emission. The _emit_event() method now copies the listeners list before iteration to prevent modification during async iteration. Scenario: 1. _emit_event() iterates listeners and awaits on_event() 2. During await, cleanup or other code calls remove_listener() 3. List modified during iteration causes RuntimeError Fix: Create a shallow copy of listeners list before iterating, allowing safe concurrent modifications without affecting ongoing iteration. Test results: All 23 tests in tests/realtime/test_openai_realtime.py passed
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a race condition in the event emission mechanism where concurrent listener list modifications during async iteration could cause runtime errors. The fix creates a snapshot of listeners before iteration to prevent RuntimeError: list changed size during iteration when listeners are removed during event processing.
Key changes:
- Added defensive copying in
_emit_event()to prevent race condition when listeners list is modified during async iteration - Added explanatory comment documenting the purpose of the list copy
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
|
@codex review |
seratch
left a comment
There was a problem hiding this comment.
This is a kind of edge case improvement but looks good to me
|
Codex Review: Didn't find any major issues. Swish! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Codex Review: Didn't find any major issues. Keep them coming! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Fixed a race condition in
OpenAIRealtimeWebSocketModel._emit_event()where the listeners list could be modified during async iteration, causingRuntimeError: list changed size during iteration.Problem
The
_emit_event()method iterates overself._listenerswhile callingawait listener.on_event(event):During the
await, other code (e.g., cleanup) can callremove_listener(), modifying the list mid-iteration.Crash scenario:
_emit_event()starts iterating listenersawait listener.on_event(), control returns to event loopremove_listener()→ modifies listThis is realistic because
remove_listener()is called during session cleanup (session.py:761).Solution
Create a shallow copy of the listeners list before iteration:
This allows safe concurrent modifications without affecting the ongoing iteration.
Testing
tests/realtime/test_openai_realtime.pypassImpact