From 20574c016a82aa2710e3d2d79eebc293b3a36112 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sat, 4 Jan 2025 00:27:33 -0500
Subject: [PATCH] coreaudio: Workaround for crash when disconnecting a
bluetooth audio device.
Our understanding of what's going on here might be incorrect, but it seems
like we're getting this callback at a point where we shouldn't be able to,
with a device we've already closed.
If we're on the wrong track, this code should still be harmless; it just
verifies a device is still in the open list before dereferencing it.
Reference Issue #10432.
---
src/audio/coreaudio/SDL_coreaudio.m | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m
index 9eb580bb1d0bb..edf6e2361743c 100644
--- a/src/audio/coreaudio/SDL_coreaudio.m
+++ b/src/audio/coreaudio/SDL_coreaudio.m
@@ -673,7 +673,21 @@ static OSStatus default_device_changed(AudioObjectID inObjectID, UInt32 inNumber
#if DEBUG_COREAUDIO
printf("COREAUDIO: default device changed for SDL audio device %p!\n", this);
#endif
- SDL_AtomicSet(&this->hidden->device_change_flag, 1); /* let the audioqueue thread pick up on this when safe to do so. */
+
+ /* due to a bug (?) in CoreAudio, this seems able to fire for a device pointer that's already closed, so check our list to make sure
+ the pointer is still valid before touching it. https://github.com/libsdl-org/SDL/issues/10432 */
+ if (open_devices) {
+ int i;
+ for (i = 0; i < num_open_devices; i++) {
+ SDL_AudioDevice *device = open_devices[i];
+ if (device == this) {
+ if (this->hidden) {
+ SDL_AtomicSet(&this->hidden->device_change_flag, 1); /* let the audioqueue thread pick up on this when safe to do so. */
+ }
+ return noErr;
+ }
+ }
+ }
return noErr;
}
#endif