Revert "audio: Device threads don't increment physical device refcounts."

This reverts commit 76f81797b7.

This worked in the normal cases, but:

A device thread that calls SDL_DisconnectAudioDevice due to failure will fire
the disconnect event from the device thread...and if there's an event watcher
that uses that moment to close the device, we still end up in the same
situation, where the device thread tries to join on itself.

Better solutions are still pending.
main
Ryan C. Gordon 2023-10-22 16:14:01 -04:00
parent e5a15f94e2
commit 33c9eeec7c
No known key found for this signature in database
GPG Key ID: FA148B892AB48044
4 changed files with 10 additions and 2 deletions

View File

@ -848,6 +848,7 @@ void SDL_QuitAudio(void)
void SDL_AudioThreadFinalize(SDL_AudioDevice *device) void SDL_AudioThreadFinalize(SDL_AudioDevice *device)
{ {
UnrefPhysicalAudioDevice(device);
} }
static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) static void MixFloat32Audio(float *dst, const float *src, const int buffer_size)
@ -863,6 +864,7 @@ static void MixFloat32Audio(float *dst, const float *src, const int buffer_size)
void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device) void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device)
{ {
SDL_assert(!device->iscapture); SDL_assert(!device->iscapture);
RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately).
current_audio.impl.ThreadInit(device); current_audio.impl.ThreadInit(device);
} }
@ -1012,6 +1014,7 @@ static int SDLCALL OutputAudioThread(void *devicep) // thread entry point
void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device) void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device)
{ {
SDL_assert(device->iscapture); SDL_assert(device->iscapture);
RefPhysicalAudioDevice(device); // unref'd when the audio thread terminates (ProvidesOwnCallbackThread implementations should call SDL_AudioThreadFinalize appropriately).
current_audio.impl.ThreadInit(device); current_audio.impl.ThreadInit(device);
} }
@ -1351,14 +1354,13 @@ void SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
if (logdev) { if (logdev) {
SDL_AudioDevice *device = logdev->physical_device; SDL_AudioDevice *device = logdev->physical_device;
DestroyLogicalAudioDevice(logdev); DestroyLogicalAudioDevice(logdev);
UnrefPhysicalAudioDevice(device); // one reference for each logical device.
// !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it. // !!! FIXME: we _need_ to release this lock, but doing so can cause a race condition if someone opens a device while we're closing it.
SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow. SDL_UnlockMutex(device->lock); // can't hold the lock or the audio thread will deadlock while we WaitThread it. If not closing, we're done anyhow.
if (device->logical_devices == NULL) { // no more logical devices? Close the physical device, too. if (device->logical_devices == NULL) { // no more logical devices? Close the physical device, too.
ClosePhysicalAudioDevice(device); ClosePhysicalAudioDevice(device);
} }
UnrefPhysicalAudioDevice(device); // one reference for each logical device.
} }
} }

View File

@ -181,6 +181,8 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
return SDL_OutOfMemory(); return SDL_OutOfMemory();
} }
RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread.
// limit to native freq // limit to native freq
device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; }); device->spec.freq = EM_ASM_INT({ return Module['SDL3'].audioContext.sampleRate; });

View File

@ -111,6 +111,8 @@ static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device)
} }
SDL_zerop(device->hidden); SDL_zerop(device->hidden);
RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread.
// Parse the audio format and fill the Be raw audio format // Parse the audio format and fill the Be raw audio format
media_raw_audio_format format; media_raw_audio_format format;
SDL_zero(format); SDL_zero(format);

View File

@ -300,6 +300,8 @@ static int JACK_OpenDevice(SDL_AudioDevice *device)
return SDL_OutOfMemory(); return SDL_OutOfMemory();
} }
RefPhysicalAudioDevice(device); // CloseDevice will always unref this through SDL_AudioThreadFinalize, even if we failed to start the thread.
client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL); client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL);
device->hidden->client = client; device->hidden->client = client;
if (client == NULL) { if (client == NULL) {