Description
Repeatedly creating, starting, stopping, and disconnecting AudioBufferSourceNode/GainNode pairs that all wrap the same, already-built AudioBuffer (the pattern required to reposition a one-shot source node - there's no seek() on a live AudioBufferSourceNode, in this library or any browser) leaks native heap. disconnect() does not release it.
A minimal repro app running 60 such "seeks" (~150ms apart, roughly human tapping speed, not synthetic max-speed spam) took resident memory from ~369 MB to 4637 MB - about 71 MB leaked per call, suspiciously close to the full buffer's own size (240s × 44100Hz × 2ch × 4 bytes ≈ 84.7 MB), which suggests each new source triggers an internal full copy of the PCM data rather than sharing/referencing the existing buffer. dumpsys meminfo confirms the leaked memory sits in Native Heap (Heap Size/Alloc reached ~5.2 GB, ~3.2 GB of it swapped to disk under the resulting pressure) - not Java/Dalvik heap, not graphics. Left running, this eventually crashes the app via a Hermes GC OOM (SIGSEGV in the mqt_v_js thread) once system memory pressure leaves nothing for Hermes to grow into.
I don't believe this is the same bug as #717 (clearOnEndedCallback, fixed in 0.10.0, which we're past) - the crash backtrace here has no react-native-audio-api frames at all (entirely inside libhermesvm.so/libreactnative.so's task scheduler, consistent with heap exhaustion rather than a direct native crash), and the leak itself is independently reproducible via dumpsys//proc/<pid>/status well before any crash occurs.
Originally found in a real app crashing under ordinary repeated seeking on a single track - the linked repro strips that down to a single-file app with no other dependencies.
Steps to reproduce
- Clone/run the linked repro
- Wait for "Ready." and note the starting RSS shown at the top
- Tap "Run 60 rapid seeks"
- Watch RSS climb continuously during the run and never drop back down afterward
- Repeat the tap a few more times / leave it running longer and the app eventually crashes with a Hermes GC OOM → SIGSEGV in
mqt_v_js
Snack or a link to a repository
https://github.com/WentTheFox/AudioApiLeakRepro
React Native Audio API version
0.13.3
React Native version
0.87.0
Platforms
Android
JavaScript runtime
Hermes
Workflow
React Native (bare CLI)
Architecture
Fabric (New Architecture)
Build type
Debug app & dev bundle
Device
Real device
Device model
Samsung Galaxy S24+ (SM-S926B), Android 16 (API 36), arm64-v8a
Acknowledgements
Yes
Description
Repeatedly creating, starting, stopping, and disconnecting
AudioBufferSourceNode/GainNodepairs that all wrap the same, already-builtAudioBuffer(the pattern required to reposition a one-shot source node - there's noseek()on a liveAudioBufferSourceNode, in this library or any browser) leaks native heap.disconnect()does not release it.A minimal repro app running 60 such "seeks" (~150ms apart, roughly human tapping speed, not synthetic max-speed spam) took resident memory from ~369 MB to 4637 MB - about 71 MB leaked per call, suspiciously close to the full buffer's own size (240s × 44100Hz × 2ch × 4 bytes ≈ 84.7 MB), which suggests each new source triggers an internal full copy of the PCM data rather than sharing/referencing the existing buffer.
dumpsys meminfoconfirms the leaked memory sits in Native Heap (Heap Size/Alloc reached ~5.2 GB, ~3.2 GB of it swapped to disk under the resulting pressure) - not Java/Dalvik heap, not graphics. Left running, this eventually crashes the app via a Hermes GC OOM (SIGSEGVin themqt_v_jsthread) once system memory pressure leaves nothing for Hermes to grow into.I don't believe this is the same bug as #717 (
clearOnEndedCallback, fixed in 0.10.0, which we're past) - the crash backtrace here has noreact-native-audio-apiframes at all (entirely insidelibhermesvm.so/libreactnative.so's task scheduler, consistent with heap exhaustion rather than a direct native crash), and the leak itself is independently reproducible viadumpsys//proc/<pid>/statuswell before any crash occurs.Originally found in a real app crashing under ordinary repeated seeking on a single track - the linked repro strips that down to a single-file app with no other dependencies.
Steps to reproduce
mqt_v_jsSnack or a link to a repository
https://github.com/WentTheFox/AudioApiLeakRepro
React Native Audio API version
0.13.3
React Native version
0.87.0
Platforms
Android
JavaScript runtime
Hermes
Workflow
React Native (bare CLI)
Architecture
Fabric (New Architecture)
Build type
Debug app & dev bundle
Device
Real device
Device model
Samsung Galaxy S24+ (SM-S926B), Android 16 (API 36), arm64-v8a
Acknowledgements
Yes