diff --git a/.changeset/ffi-client-singleton-lock.md b/.changeset/ffi-client-singleton-lock.md new file mode 100644 index 00000000..2aabdd8c --- /dev/null +++ b/.changeset/ffi-client-singleton-lock.md @@ -0,0 +1,5 @@ +--- +"livekit-rtc": patch +--- + +Create the shared `FfiClient` under a lock, so rooms connected from several threads at once no longer lose their connect callback and panic the process. diff --git a/livekit-rtc/livekit/rtc/_ffi_client.py b/livekit-rtc/livekit/rtc/_ffi_client.py index 096b7ea5..d45c3247 100644 --- a/livekit-rtc/livekit/rtc/_ffi_client.py +++ b/livekit-rtc/livekit/rtc/_ffi_client.py @@ -231,12 +231,17 @@ def to_python_level(level: proto_ffi.LogLevel.ValueType) -> Optional[int]: class FfiClient: _instance: Optional["FfiClient"] = None _ffi_disposed: bool = False + _instance_lock = threading.Lock() @classproperty def instance(cls) -> "FfiClient": - if cls._instance is None: - cls._instance = FfiClient() - return cls._instance + if cls._instance is not None: + return cls._instance + # threads that race here would each get their own client and lose events sent to the other + with cls._instance_lock: + if cls._instance is None: + cls._instance = FfiClient() + return cls._instance def __init__(self) -> None: FfiClient._ffi_disposed = False