Skip to content

Commit c9b34f6

Browse files
committed
rtc: fail fast instead of hanging when FFI is used across fork()
The native runtime (tokio worker/IO threads in liblivekit_ffi) does not survive fork() and cannot be rebuilt by re-initializing, so a child that inherited an initialized FFI singleton would hang on every request. Guard FfiClient.instance with the owning pid and raise a clear error instead.
1 parent 3f92f3c commit c9b34f6

1 file changed

Lines changed: 15 additions & 3 deletions

File tree

livekit-rtc/livekit/rtc/_ffi_client.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,23 @@ class FfiClient:
213213

214214
@classproperty
215215
def instance(cls) -> "FfiClient":
216-
if cls._instance is None:
217-
cls._instance = FfiClient()
218-
return cls._instance
216+
inst = cls._instance
217+
if inst is not None and inst._pid != os.getpid():
218+
# The native runtime (tokio worker/IO threads inside liblivekit_ffi)
219+
# does not survive fork(), and re-initializing does not rebuild it,
220+
# so a child that inherited an initialized FFI hangs on every request.
221+
# Fail loudly instead of hanging.
222+
raise RuntimeError(
223+
"livekit.rtc was used in a parent process before fork(); the native "
224+
"runtime cannot be used across fork(). Do not create or connect a Room "
225+
"(or use any livekit.rtc object) before forking child processes."
226+
)
227+
if inst is None:
228+
cls._instance = inst = FfiClient()
229+
return inst
219230

220231
def __init__(self) -> None:
232+
self._pid = os.getpid()
221233
self._lock = threading.RLock()
222234
self._queue = FfiQueue[proto_ffi.FfiEvent]()
223235

0 commit comments

Comments
 (0)