Skip to content

Fix: only latch WebRTC initialization after PeerConnectionFactory.initialize succeeds - #992

Open
shivanshu877 wants to merge 2 commits into
livekit:mainfrom
shivanshu877:fix/webrtc-init-latch
Open

Fix: only latch WebRTC initialization after PeerConnectionFactory.initialize succeeds#992
shivanshu877 wants to merge 2 commits into
livekit:mainfrom
shivanshu877:fix/webrtc-init-latch

Conversation

@shivanshu877

Copy link
Copy Markdown

Problem

RTCModule.libWebrtcInitialization sets hasInitializedWebrtc = true before calling PeerConnectionFactory.initialize(...). If initialization throws — most commonly when the native library fails to dlopen on a corrupted or partial install (missing arm64 split from sideloaded APKs, app cloners, broken Play delivery; see #572 for the same underlying load failure) — the latch stays set for the lifetime of the process.

The first LiveKit.create() then fails with a catchable exception (executeBlockingOnRTCThread runs the block via executor.submit(...).get(), so the UnsatisfiedLinkError surfaces wrapped in ExecutionException). Apps that catch it and later retry hit the poisoned latch: the second LiveKit.create() skips initialization entirely and crashes at the first native call in the Dagger graph:

java.lang.UnsatisfiedLinkError: No implementation found for long livekit.org.webrtc.ExternalAudioProcessingFactory.nativeGetDefaultApm()
    at livekit.org.webrtc.ExternalAudioProcessingFactory.nativeGetDefaultApm(Native Method)
    at livekit.org.webrtc.ExternalAudioProcessingFactory.<init>
    at io.livekit.android.webrtc.CustomAudioProcessingFactory.<init>
    at io.livekit.android.dagger.RTCModule.customAudioProcessingFactory
    ...
    at io.livekit.android.LiveKit$Companion.create

Because this second failure is a raw Error on the caller's thread (not wrapped by a Future), typical catch (Exception) handling cannot intercept it and the app process dies. We see this pattern in production via Crashlytics.

Fix

Set hasInitializedWebrtc = true only after PeerConnectionFactory.initialize returns. A failed initialization stays retryable (webrtc's own NativeLibrary.libraryLoaded also remains false when loadLibrary throws, so a retry genuinely re-attempts the load), and every failed attempt surfaces as a catchable exception at the LiveKit.create() call site instead of a fatal, uncatchable crash on the second call.

Notes

  • Repro: make System.loadLibrary("lkjingle_peerconnection_so") fail (e.g. temporarily rename the lib in a test build), call LiveKit.create() twice in one process catching Exception around each call. Before this change: first call throws ExecutionException, second call dies with the UnsatisfiedLinkError above. After: both calls throw catchably.
  • No behavior change on the success path.

🤖 Generated with Claude Code

…tialize succeeds

If PeerConnectionFactory.initialize throws (e.g. the native library fails
to dlopen on a corrupted/partial install), hasInitializedWebrtc was
already set to true, so every subsequent LiveKit.create() in the process
skipped initialization and crashed at the first native call
(ExternalAudioProcessingFactory.nativeGetDefaultApm) with an
UnsatisfiedLinkError that cannot be caught as an Exception.

Setting the latch only after initialize returns keeps failed
initialization retryable and surfaces the underlying load failure as a
catchable exception at the call site on every attempt.
@changeset-bot

changeset-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 22fa35b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
client-sdk-android Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@CLAassistant

CLAassistant commented Aug 3, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

devin-ai-integration[bot]

This comment was marked as resolved.

@davidliu davidliu 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.

LGTM, can you sign the CLA and add a changeset? Instructions are found here:
https://github.com/livekit/client-sdk-android/blob/main/CONTRIBUTING.md

@shivanshu877

Copy link
Copy Markdown
Author

Done — changeset added and CLA signed. All checks are green; ready for merge. Thanks for the quick 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.

3 participants