From 982b778e45b13cb3510eb375afd0175240d1080a Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 24 Apr 2025 10:29:36 -0400
Subject: [PATCH] audio: SDL_GetAudioDeviceName() doesn't need a full device
lock.
Fixes https://github.com/libsdl-org/sdl2-compat/issues/468
(cherry picked from commit e8bd9cc150b7e54c24e005327511976cb102d005)
---
src/audio/SDL_audio.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index cf817e4f19a12..890d2844f0423 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -1502,12 +1502,32 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle)
const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
{
+ bool isstack;
+ char *string = NULL;
const char *result = NULL;
- SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid);
+ SDL_AudioDevice *device = NULL;
+
+ // This does not call ObtainPhysicalAudioDevice() because the device's name never changes, so
+ // it doesn't have to lock the whole device. However, just to make sure the device pointer itself
+ // remains valid (in case the device is unplugged at the wrong moment), we hold the
+ // device_hash_lock while we copy the string.
+ SDL_LockRWLockForReading(current_audio.device_hash_lock);
+ SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &device);
if (device) {
- result = SDL_GetPersistentString(device->name);
+ const size_t slen = SDL_strlen(device->name) + 1;
+ // SDL_GetPersistentString might _also_ makes a copy, but it might also create a TLS slot and a hashtable before doing a lookup, malloc+copy, and insert.
+ // So just try to tuck this into a little stack space while we're holding device_hash_lock.
+ string = SDL_small_alloc(char, slen, &isstack);
+ if (string) {
+ SDL_strlcpy(string, device->name, slen);
+ }
+ }
+ SDL_UnlockRWLock(current_audio.device_hash_lock);
+
+ if (string) {
+ result = SDL_GetPersistentString(string);
+ SDL_small_free(string, isstack);
}
- ReleaseAudioDevice(device);
return result;
}