From 484d5fd6cfaf7abdd6d20b9838bbdac8c97bba2d Mon Sep 17 00:00:00 2001 From: Nicolas Cian Date: Wed, 5 Oct 2022 13:19:38 +0200 Subject: [PATCH] audio open: ensure 2 devices don't get the same id --- src/audio/SDL_audio.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index e2f7412c9..e33e41dbc 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1313,7 +1313,7 @@ open_audio_device(const char *devname, int iscapture, return 0; } - /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */ + SDL_LockMutex(current_audio.detectionLock); /* Find an available device ID... */ for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) { if (open_devices[id] == NULL) { @@ -1323,6 +1323,7 @@ open_audio_device(const char *devname, int iscapture, if (id == SDL_arraysize(open_devices)) { SDL_SetError("Too many open audio devices"); + SDL_UnlockMutex(current_audio.detectionLock); return 0; } @@ -1330,6 +1331,7 @@ open_audio_device(const char *devname, int iscapture, obtained = &_obtained; } if (!prepare_audiospec(desired, obtained)) { + SDL_UnlockMutex(current_audio.detectionLock); return 0; } @@ -1351,6 +1353,7 @@ open_audio_device(const char *devname, int iscapture, if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) { if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) { SDL_SetError("No such device"); + SDL_UnlockMutex(current_audio.detectionLock); return 0; } devname = NULL; @@ -1358,11 +1361,13 @@ open_audio_device(const char *devname, int iscapture, for (i = 0; i < SDL_arraysize(open_devices); i++) { if ((open_devices[i]) && (open_devices[i]->iscapture)) { SDL_SetError("Audio device already open"); + SDL_UnlockMutex(current_audio.detectionLock); return 0; } } } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) { + SDL_UnlockMutex(current_audio.detectionLock); SDL_SetError("No such device"); return 0; } @@ -1370,6 +1375,7 @@ open_audio_device(const char *devname, int iscapture, for (i = 0; i < SDL_arraysize(open_devices); i++) { if ((open_devices[i]) && (!open_devices[i]->iscapture)) { + SDL_UnlockMutex(current_audio.detectionLock); SDL_SetError("Audio device already open"); return 0; } @@ -1382,20 +1388,19 @@ open_audio_device(const char *devname, int iscapture, It might still need to open a device based on the string for, say, a network audio server, but this optimizes some cases. */ SDL_AudioDeviceItem *item; - SDL_LockMutex(current_audio.detectionLock); for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) { if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) { handle = item->handle; break; } } - SDL_UnlockMutex(current_audio.detectionLock); } if (!current_audio.impl.AllowsArbitraryDeviceNames) { /* has to be in our device list, or the default device. */ if ((handle == NULL) && (devname != NULL)) { SDL_SetError("No such device."); + SDL_UnlockMutex(current_audio.detectionLock); return 0; } } @@ -1403,6 +1408,7 @@ open_audio_device(const char *devname, int iscapture, device = (SDL_AudioDevice *) SDL_calloc(1, sizeof (SDL_AudioDevice)); if (device == NULL) { SDL_OutOfMemory(); + SDL_UnlockMutex(current_audio.detectionLock); return 0; } device->id = id + 1; @@ -1419,6 +1425,7 @@ open_audio_device(const char *devname, int iscapture, device->mixer_lock = SDL_CreateMutex(); if (device->mixer_lock == NULL) { close_audio_device(device); + SDL_UnlockMutex(current_audio.detectionLock); SDL_SetError("Couldn't create mixer lock"); return 0; } @@ -1433,6 +1440,7 @@ open_audio_device(const char *devname, int iscapture, if (current_audio.impl.OpenDevice(device, devname) < 0) { close_audio_device(device); + SDL_UnlockMutex(current_audio.detectionLock); return 0; } @@ -1488,6 +1496,7 @@ open_audio_device(const char *devname, int iscapture, if (!device->stream) { close_audio_device(device); + SDL_UnlockMutex(current_audio.detectionLock); return 0; } } @@ -1497,6 +1506,7 @@ open_audio_device(const char *devname, int iscapture, device->buffer_queue = SDL_NewDataQueue(SDL_AUDIOBUFFERQUEUE_PACKETLEN, obtained->size * 2); if (!device->buffer_queue) { close_audio_device(device); + SDL_UnlockMutex(current_audio.detectionLock); SDL_SetError("Couldn't create audio buffer queue"); return 0; } @@ -1514,6 +1524,7 @@ open_audio_device(const char *devname, int iscapture, device->work_buffer = (Uint8 *) SDL_malloc(device->work_buffer_len); if (device->work_buffer == NULL) { close_audio_device(device); + SDL_UnlockMutex(current_audio.detectionLock); SDL_OutOfMemory(); return 0; } @@ -1534,9 +1545,11 @@ open_audio_device(const char *devname, int iscapture, if (device->thread == NULL) { close_audio_device(device); SDL_SetError("Couldn't create audio thread"); + SDL_UnlockMutex(current_audio.detectionLock); return 0; } } + SDL_UnlockMutex(current_audio.detectionLock); return device->id; }