Skip to content

test: don't report GC-scheduled close tasks as leaks - #6790

Open
hassannaftabb wants to merge 1 commit into
livekit:mainfrom
hassannaftabb:fix/leak-check-transient-tasks
Open

test: don't report GC-scheduled close tasks as leaks#6790
hassannaftabb wants to merge 1 commit into
livekit:mainfrom
hassannaftabb:fix/leak-check-transient-tasks

Conversation

@hassannaftabb

Copy link
Copy Markdown

Closes #6789.

Problem

fail_on_leaked_tasks diffs asyncio.all_tasks() around the test body on its non-concurrent path. Garbage-collector finalization schedules short-lived close tasks onto whichever loop is running, so such a task can be pending at the instant the loop is sampled without having been leaked by the test that was executing. google-genai's AsyncClient.__del__ calls aclose() exactly this way — test_plugin_google_realtime.py already documents the behaviour in _make_session:

Closed on exit so the genai http clients are released here instead of by AsyncClient.__del__, which schedules aclose() on whatever event loop is running when the collector happens to reach them.

That mitigation only covers the client that test constructs. The result is test_output_streams_close_on_generation_complete erroring at teardown with BaseApiClient.aclose / AsyncClient.aclose in the leak list — only in full-suite runs, never in isolation. I saw four consecutive failures and then two clean runs with no code change in between.

Change

Before failing, give the tasks that are about to be reported a bounded moment to finish. A GC-scheduled close finishes in a turn or two; a genuine leak is still pending afterwards. The wait only happens on the path that was about to fail, so a passing run does no extra work.

Why not widen the ignore list

The issue offered ignoring genai's close coroutines in _is_ignorable_task as one option. I went the other way: an ignore entry would suppress these tasks permanently, including a real leak of a genai client from the plugin itself. Settling distinguishes the two by behaviour rather than by name, and needs no per-library entries as more SDKs get added.

Tests

tests/test_leak_check.py covers both directions, and both failed before the change (on ImportError, the helper did not exist):

  • test_settle_drops_a_task_that_finishes_on_its_own — a task pending at sample time but finishing immediately after is not reported
  • test_settle_keeps_a_task_that_never_finishes — a task that never completes is still reported

I also checked detection end-to-end rather than only through the helper: running a test module that genuinely leaks a task still produces the Test leaked tasks error with this change applied.

Verification

pytest --unit gives 1927 passed over three consecutive runs, ruff check and ruff format --check clean. Run in a Linux container with the docker socket mounted so tests/lk_server.py can start livekit-server; tests/test_room.py cannot pass without that.

Worth saying plainly: this is an intermittent failure, so a run of clean passes is not proof on its own. The deterministic tests above are the real evidence — they pin the mechanism rather than the symptom.

fail_on_leaked_tasks samples asyncio.all_tasks() around the test body, so a task
that garbage-collector finalization schedules onto the running loop is attributed
to whichever test happened to be executing. google-genai's AsyncClient.__del__
calls aclose() that way, which makes test_output_streams_close_on_generation_complete
fail intermittently in full-suite runs while passing in isolation.

Give the tasks that are about to be reported a bounded moment to finish before
failing. A GC-scheduled close completes in a turn or two; a real leak is still
pending afterwards, so detection is unchanged.

Closes livekit#6789
@hassannaftabb
hassannaftabb requested a review from a team as a code owner August 11, 2026 12:55

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky unit test: GC-scheduled google-genai aclose tasks trip fail_on_leaked_tasks in unrelated tests

1 participant