Skip to content

PlatformAudio stability/shutdown#1193

Draft
alan-george-lk wants to merge 3 commits into
mainfrom
feature/platform-audio-stability
Draft

PlatformAudio stability/shutdown#1193
alan-george-lk wants to merge 3 commits into
mainfrom
feature/platform-audio-stability

Conversation

@alan-george-lk

@alan-george-lk alan-george-lk commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Before you submit your PR

Make sure the following is true before submitting your PR:

  • I have read the contributing guidelines and validated that this PR will be accepted.
  • I have read and followed the principles regarding breaking changes, testing, and code quality.

PR description

It was discovered in client-sdk-cpp action runs that macOS integration tests intermittently crashed during PlatformAudioIntegrationTest.PublishPlatformAudioTrackEndToEnd, often after MediaMultiStreamIntegrationTest completed. The stack showed AudioDeviceMac::CaptureWorkerThread still delivering captured audio into AudioTransportImpl while peer connection transports (JsepTransportController / BundleManager) were being torn down — a native ADM shutdown ordering bug, not a C++ test artifact.

Breaking changes

N/A

MSRV

N/A

Testing

Ideally, unit test the code you add, but ensure you're not repeating existing test cases. Use as many already written scaffolding, utilities as possible; write your own, when needed. If external services, APIs, tokens are required (e.g., running an LK server instance), provide the necessary information. Make sure your tests perform useful, context-aware assertions and do not simply emulate "happy paths".

Async

We want the project to be runtime-agnostic, so please reuse what's already in livekit-runtime and feel free to add anything missing. It's ok to use Tokio directly, when writing unit tests, if necessary. When testing, do not use artificial delays for the state to "catch up"; instead, respect the event flow and subscribe properly using channels or other mechanisms.

@github-actions

Copy link
Copy Markdown
Contributor

Changeset

The following package versions will be affected by this PR:

Package Bump
libwebrtc minor
livekit minor
livekit-ffi patch
webrtc-sys patch

@xianshijing-lk xianshijing-lk 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 in general, some comments

Comment thread webrtc-sys/include/livekit/adm_proxy.h Outdated

// Stops active capture/playout and detaches audio callbacks from both ADMs.
// Must be called with mutex_ held.
void StopAudioIOLocked();

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.

you already document that this function needs to be called under a mutex_, so you don't need to name it StopAudioIOLocked(), just StopAudioIO() or just StopAudio

Comment thread webrtc-sys/include/livekit/adm_proxy.h Outdated

// Stops platform capture/playout and detaches its callback without touching
// synthetic mode. Must be called with mutex_ held.
void StopPlatformAudioIOLocked();

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.

ditto

if (platform_adm_) {
platform_adm_->RegisterAudioCallback(nullptr);
platform_adm_->StopRecording();
platform_adm_->StopPlayout();

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.

nit, curiously, why couldn't we set platform_adm_ = nullptr after calling StopXXX() function ?

if (synthetic_adm_) {
synthetic_adm_->RegisterAudioCallback(nullptr);
synthetic_adm_->StopRecording();
synthetic_adm_->StopPlayout();

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.

same here

Comment thread webrtc-sys/include/livekit/adm_proxy.h Outdated
///
/// Call before tearing down the peer connection factory so capture worker
/// threads cannot deliver frames into transports that are being destroyed.
void ShutdownAudioIO();

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.

I think you can use StopAudioIOLocked directly without ShutdownAudioIO(); ?

alan-george-lk and others added 3 commits June 30, 2026 12:39
Clear remaining FFI handles during dispose so native resources are
released across repeated initialize/shutdown cycles.

Stop and detach platform/synthetic audio I/O before peer connection
factory teardown so macOS CaptureWorkerThread cannot deliver frames
into AudioTransportImpl while transports are being destroyed. Close
rooms before dropping track handles and stop platform capture when
releasing the platform ADM reference.

Co-authored-by: Cursor <cursoragent@cursor.com>
Rename the changeset and document the full ADM teardown + FFI dispose
fix. Bump livekit and libwebrtc as minor for the new shutdown_audio_io
lifecycle hooks; keep livekit-ffi and webrtc-sys as patch.

Co-authored-by: Cursor <cursoragent@cursor.com>
Rename StopAudioIOLocked/StopPlatformAudioIOLocked to StopAudioIO and
StopPlatformAudioIO, collapse ShutdownAudioIO into public StopAudioIO,
and document why ADM instances are retained after stopping I/O.

Co-authored-by: Cursor <cursoragent@cursor.com>
@alan-george-lk alan-george-lk force-pushed the feature/platform-audio-stability branch from 40a4677 to d3bb145 Compare June 30, 2026 18:41
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