Skip to content

Intermittent abort at interpreter exit: "panic in a function that cannot unwind" on a tokio-rt-worker after livekit_ffi_dispose (livekit 1.1.18 and 1.1.20) #833

Description

@skyzer

Summary

A short Python script that uses the FFI and then returns normally sometimes aborts during interpreter shutdown, with exit code 134. This happens in about 0.5-1% of runs. It started as a flaky Docker build step for us.

thread 'tokio-rt-worker' (N) panicked at /rustc/8bab26f4f68e0e26f0bb7960be334d5b520ea452/library/core/src/panicking.rs:225:5:
panic in a function that cannot unwind
thread caused non-unwinding panic. aborting.
Aborted (core dumped)

Versions

  • livekit 1.1.18 (bundled livekit-ffi 0.12.76), pinned by livekit-agents 1.8.1–1.8.3
  • It reproduces the same way with livekit 1.1.20 installed over it.
  • Python 3.12.13 (python:3.12.13-slim-bookworm), Linux x86_64 (CI) and aarch64 (local Docker)

Reproduction

import asyncio
from livekit.agents.voice.background_audio import BackgroundAudioPlayer

async def main():
    player = BackgroundAudioPlayer()   # creates an rtc.AudioSource
    await player.aclose()

asyncio.run(main())

Run it in a loop, for example for i in $(seq 1 400); do python repro.py || echo fail; done. We saw about 2 aborts in 200 runs on 1.1.18, and 2 in 400 with 1.1.20.

What we observed

  • Every abort happens after asyncio.run(main()) has returned. A marker printed right after it is always present in the output.
  • Under gdb, the main thread is in Py_FinalizeEx → PyGC_Collect, which runs after the atexit hook that calls livekit_ffi_dispose(). The aborting thread is a tokio-rt-worker that gdb reports as "(Exiting)". It panics inside liblivekit_ffi.so during thread exit, where the panic cannot unwind, so the process aborts.
  • It looks like a runtime worker thread (possibly one spawned during teardown) outlives or races livekit_ffi_dispose(), and panics in a thread-local destructor or thread-exit path.
  • Ending the script with os._exit(0), which skips finalization, gave 0 aborts in 1,000 runs.

Expected

A process that has finished using the SDK exits with status 0. Or, if the runtime cannot shut down cleanly, it does not abort.

Impact for us

  • Build-time smoke checks that construct SDK audio objects fail about 1% of the time.
  • Agent job processes are not affected, because they end with os._exit from the multiprocessing forkserver.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions