Skip to content

fix(tests): run FFI dispose test in a subprocess and add test timeouts - #931

Open
cloudwebrtc wants to merge 2 commits into
mainfrom
fix/ffi-dispose-test-isolation
Open

cloudwebrtc wants to merge 2 commits into
mainfrom
fix/ffi-dispose-test-isolation

Conversation

@cloudwebrtc

@cloudwebrtc cloudwebrtc commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Since #857 (bb3ed60), every build-rtc.yml run that has LiveKit credentials gets cancelled after the 6h job limit. All Test jobs on every platform stop after test_rpc_interceptors.py [99%] and never finish livekit-rtc/tests/test_video.py. Runs from fork PRs show as green only because they have no secrets, so test_video.py is skipped.

The cause is test_live_handles_marked_consumed_and_no_assert_after_dispose in test_ffi_handle_lifecycle.py. It calls FfiClient.instance._dispose() inside the pytest process. That calls livekit_ffi_dispose(), which tears down the process-wide FFI runtime and leaves FfiClient._ffi_disposed = True. Every later test that waits on an FFI callback then blocks forever. test_video.py is the next such test in collection order, and its Room.connect() has no timeout.

Local reproduction: run the old lifecycle test file, then a test that awaits AudioSource.capture_frame(). The second test never gets its FFI callback and times out. With this change, it passes.

Changes

  • Move the dispose test into a fresh interpreter (subprocess.run([sys.executable, "-c", ...])), the same way the existing subprocess-exit test in this file works. Its assertions are unchanged.

  • tests.yml: install pytest-timeout and run with --timeout=300. Set timeout-minutes: 45 on the test job so a future hang fails quickly with a traceback instead of waiting for the 6h limit.

  • test_dc.py::test_publish_data_makes_no_ctypes_array_type: replace isinstance(o, type) with issubclass(type(o), type) when scanning gc.get_objects(). On Windows ARM64 the gc list can contain a weakref.proxy whose referent is gone. isinstance() dereferences it and raises ReferenceError: weakly-referenced object no longer exists. type(o) does not dereference the proxy, and ctypes array types are still matched.

Not addressed here

  • Linux / Python 3.12: test_ffi_client.py reported F in an earlier hung run. The job was killed before the error was printed, and it has not reproduced on this PR so far.

test_live_handles_marked_consumed_and_no_assert_after_dispose called
FfiClient._dispose() inside the pytest process, which tears down the
process-wide FFI runtime. Every later test that waits on an FFI callback
then hangs forever; test_video.py (which only runs when LiveKit
credentials are set) blocked every Test job until the 6h job limit.

- Run the dispose test in a fresh interpreter, like the existing
  subprocess-exit test in the same file.
- Add pytest-timeout (--timeout=300) and a 45 minute job timeout so a
  hang fails fast with a traceback instead of being cancelled after 6h.
@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

👋 This PR has no changeset. If it should be released, add a markdown file under .changeset/ (any name, e.g. .changeset/fix-token-parsing.md):

---
"livekit-rtc": patch
---

Short description of the change, used in the release notes.
  • Packages: livekit-rtc, livekit-api, livekit-protocol (one line per package)
  • Types: patch, minor, major, patch-rc, minor-rc, major-rc, next-rc, promote

If this change doesn't need a release (docs, CI, tests), you can ignore this comment.

@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 bugs or issues to report.

Devin Review

…ay types

On Windows ARM64, gc.get_objects() can return a weakref.proxy whose
referent is already gone. isinstance(o, type) dereferences the proxy and
raises ReferenceError. Check issubclass(type(o), type) instead, which
reads the proxy's own type without dereferencing it.

This branch has not been deployed

No deployments
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.

2 participants