Skip to content

fix: retire AVAudioEngine after configuration changes - #216

Merged
jatinkrmalik merged 1 commit into
mainfrom
jatin/fix-audio-engine-config-change-uaf-b1e1
Aug 13, 2026
Merged

fix: retire AVAudioEngine after configuration changes#216
jatinkrmalik merged 1 commit into
mainfrom
jatin/fix-audio-engine-config-change-uaf-b1e1

Conversation

@jatinkrmalik

Copy link
Copy Markdown
Member

Summary

Fixes the rest of #196. The HFP settle wait in #197 got Soundcore recordings to start, but later reports from @cbauer42 show the same path still crashing and interrupting recordings.

Crash

handleAudioConfigurationChange called releaseEngine(), which dropped the last reference to AVAudioEngine while AVFAudio was still in AVAudioIOUnit::IOUnitPropertyListener. That is the EXC_BAD_ACCESS on macOS 26.6 and 26.6.1. Apple documents this notification as: do not deallocate the engine from the client's handler.

Erratic recordings

Bluetooth A2DP/HFP switches keep posting configuration changes after start. We treated those as a lost microphone, force-stopped, and destroyed the engine. That matches the menu bar audio icon appearing and disappearing, Music.app launching on its own, and CADefaultDeviceAggregate showing up in the dropdown.

Fix

  • Detach the invalidated engine immediately so the next recording cannot reuse it, but keep the old AVAudioEngine alive for idleEngineReleaseDelay so AVFAudio can finish its callbacks.
  • If we are still recording and the graph actually stopped, rebuild the tap on the existing engine instead of aborting the session.
  • Hide CADefaultDeviceAggregate from the mic picker and treat it as a healthy transient route while HFP is settling.

Tests

Unit coverage for aggregate detection, picker filtering, route health, and the startup ignore window.

Hardware check

Please try a Bluetooth headset (Soundcore Liberty 5 / AirPods):

  1. Push-to-talk should record without a red flash or a crash.
  2. Repeat PTT a few times. The menu bar audio icon should stay put instead of flickering.
  3. CADefaultDeviceAggregate should not appear in the mic dropdown.
  4. Unplugging a wired mic mid-recording should still stop and recover.
Open in Web Open in Cursor 

Bluetooth HFP settle posts AVAudioEngineConfigurationChange, and
releaseEngine() in that handler deallocates AVAudioIOUnit while Core
Audio is still in IOUnitPropertyListener (EXC_BAD_ACCESS on macOS 26).

Detach the invalidated engine immediately so the next recording gets a
fresh instance, keep the old object alive until AVFAudio callbacks
drain, and restart the graph in place when a recording is still active.
Hide CADefaultDeviceAggregate from the mic picker and treat it as a
healthy transient route during profile switches.

Fixes #196
@github-actions github-actions Bot added app bug Something isn't working web and removed web labels Aug 13, 2026
@jatinkrmalik
jatinkrmalik marked this pull request as ready for review August 13, 2026 17:17
@jatinkrmalik
jatinkrmalik merged commit 23592f8 into main Aug 13, 2026
5 checks passed
@cbauer42

Copy link
Copy Markdown

Tried the nightly but now it doesn't work at all. So my guess is that you have a fundamental issue here that prevents the app from working when audio devices change on macOS. I plug in my audio interface or connect my BT headset -> weird things happen.

@jatinkrmalik

Copy link
Copy Markdown
Member Author

@cbauer42 Did you try this build because I just built it with this commit? https://github.com/VocaHQ/vocamac/releases/tag/nightly ?

@jatinkrmalik
jatinkrmalik deleted the jatin/fix-audio-engine-config-change-uaf-b1e1 branch August 22, 2026 05:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants