Skip to content

fix(realtime): await background tasks during cleanup#3656

Open
gyx09212214-prog wants to merge 3 commits into
openai:mainfrom
gyx09212214-prog:fix-realtime-cleanup-awaits-tasks
Open

fix(realtime): await background tasks during cleanup#3656
gyx09212214-prog wants to merge 3 commits into
openai:mainfrom
gyx09212214-prog:fix-realtime-cleanup-awaits-tasks

Conversation

@gyx09212214-prog

Copy link
Copy Markdown

Summary

Fixes #3334.

RealtimeSession._cleanup() now cancels and awaits pending guardrail and tool-call background tasks before clearing their tracking sets and continuing model shutdown. This ensures cancellation finally blocks finish before cleanup returns, and avoids processing task cancellation after the session has already moved on to closing the model.

What changed

  • Added a shared cleanup helper that cancels tracked background tasks and awaits them with return_exceptions=True.
  • Updated guardrail and tool-call cleanup paths to use that helper.
  • Added a regression test that creates pending guardrail/tool-call tasks, calls _cleanup(), and asserts both tasks are done and their finally blocks ran before cleanup returns.

Test plan

  • python -m pytest tests/realtime/test_session.py -q
  • python -m ruff check src/agents/realtime/session.py tests/realtime/test_session.py
  • python -m ruff format --check src/agents/realtime/session.py tests/realtime/test_session.py
  • python -m py_compile src/agents/realtime/session.py tests/realtime/test_session.py
  • git diff --check

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be773870d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread src/agents/realtime/session.py Outdated
if tasks_to_await:
await asyncio.gather(*tasks_to_await, return_exceptions=True)

tasks.clear()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't drop tasks added during cleanup

When cleanup is awaiting cancellation finalizers, the session is still accepting model events because the listener is removed only after these awaits. If a transcript/function_call event or approval path enqueues another task after list(tasks) is taken, tasks.clear() removes that new live task from tracking without cancelling or awaiting it, so it can continue after close() and send events to a model that is being closed. Consider marking the session closing/removing the listener before awaiting, or only discarding the snapshot and looping until no tracked tasks remain.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 14d12e901f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

self._cleanup_tool_call_tasks()

# Remove ourselves as a listener
self._model.remove_listener(self)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent in-flight events from enqueuing after cleanup

Removing the listener here does not stop model events that already copied this listener before close() began; fresh evidence is OpenAIRealtimeModel._emit_event in src/agents/realtime/openai_realtime.py lines 624-626, which iterates over list(self._listeners) and then awaits listener.on_event(event). When close() races with an already-dispatched function_call and _tool_call_tasks is still empty, _cleanup_tool_call_tasks() returns before that in-flight on_event reaches _enqueue_tool_call_task, so the newly added tool task is never cancelled or awaited and can continue after the session is closed.

Useful? React with 👍 / 👎.

@seratch seratch added duplicate This issue or pull request already exists feature:realtime labels Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists feature:realtime

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Realtime cleanup should await cancelled background tasks

2 participants