From f71979dcb3a2988b8f40158bf89512ce1d660b76 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" 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. (cherry picked from commit 20574c016a82aa2710e3d2d79eebc293b3a36112) --- 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 0cdc3ec2a6..ff982b66b9 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