Skip to content

Fix fire-and-forget event tasks in RealtimeSession#3553

Open
kratos0718 wants to merge 1 commit into
openai:mainfrom
kratos0718:fix/floating-tasks-in-realtime-session
Open

Fix fire-and-forget event tasks in RealtimeSession#3553
kratos0718 wants to merge 1 commit into
openai:mainfrom
kratos0718:fix/floating-tasks-in-realtime-session

Conversation

@kratos0718

Copy link
Copy Markdown

Summary

RealtimeSession emitted three error events via a bare asyncio.create_task(self._put_event(...)) whose result was discarded (in _on_guardrail_task_done and _on_tool_call_task_done).

asyncio only keeps a weak reference to a task, so a fire-and-forget task can be garbage-collected before it runs (documented behavior). When that happens here, the error event it was meant to deliver is silently dropped — and these are exactly the paths that report guardrail/tool-call failures to the caller.

The session already uses a keep-a-reference pattern for _guardrail_tasks and _tool_call_tasks (a tracking set + add_done_callback(discard)). This change applies the same pattern to the event-emitting tasks via a small _emit_event_soon helper, and cancels any still-pending event tasks during _cleanup.

Test plan

  • Added tests/realtime/test_session_event_tasks.py:
    • _emit_event_soon holds a strong reference while the task is pending, delivers the event to the queue, and releases the reference once done.
    • _cleanup_event_tasks cancels pending event tasks.
  • make format, make lint pass (ruff).

Issue number

N/A — found via static analysis of fire-and-forget create_task usage.

Checks

  • I've added new tests (if relevant)
  • I've added/updated the relevant documentation (n/a — internal behavior)
  • I've run make lint and make format
  • I've made sure tests pass

Three error events were emitted with a bare asyncio.create_task(self._put_event(...))
whose result was discarded. asyncio only keeps a weak reference to a task, so
these tasks could be garbage-collected before running, silently dropping the
error events they were meant to deliver.

Route them through a new _emit_event_soon helper that retains a strong reference
in a tracking set until the task completes (mirroring the existing
_guardrail_tasks and _tool_call_tasks pattern), and cancel any pending event
tasks during cleanup. Adds regression tests.
@github-actions

Copy link
Copy Markdown
Contributor

This PR is stale because it has been open for 10 days with no activity.

@github-actions github-actions Bot added the stale label Jun 16, 2026
@kratos0718

Copy link
Copy Markdown
Author

Gentle bump 🙂 This is still relevant: the three asyncio.create_task(...) results in RealtimeSession are discarded, so under GC pressure the error events those tasks emit can be dropped silently. The fix keeps a strong reference to each task until it completes (and removes it on done). Happy to rebase onto main or address any feedback whenever a maintainer has a chance to take a look — thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants