|
@@ -734,11 +734,10 @@ SDL_AudioDevice *SDL_AddAudioDevice(bool recording, const char *name, const SDL_
|
|
|
}
|
|
|
|
|
|
// Called when a device is removed from the system, or it fails unexpectedly, from any thread, possibly even the audio device's thread.
|
|
|
-void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
|
|
|
+static void SDLCALL SDL_AudioDeviceDisconnected_OnMainThread(void *userdata)
|
|
|
{
|
|
|
- if (!device) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
|
|
|
+ SDL_assert(device != NULL);
|
|
|
|
|
|
// Save off removal info in a list so we can send events for each, next
|
|
|
// time the event queue pumps, in case something tries to close a device
|
|
@@ -808,6 +807,23 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
|
|
|
|
|
|
UnrefPhysicalAudioDevice(device);
|
|
|
}
|
|
|
+
|
|
|
+ // We always ref this in SDL_AudioDeviceDisconnected(), so if multiple attempts
|
|
|
+ // to disconnect are queued, the pointer stays valid until the last one comes
|
|
|
+ // through.
|
|
|
+ UnrefPhysicalAudioDevice(device);
|
|
|
+}
|
|
|
+
|
|
|
+void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
|
|
|
+{
|
|
|
+ // lots of risk of various audio backends deadlocking because they're calling
|
|
|
+ // this while holding a backend-specific lock, which causes problems when we
|
|
|
+ // want to obtain the device lock while its audio thread is also waiting for
|
|
|
+ // that lock to be released. So just queue the work on the main thread.
|
|
|
+ if (device) {
|
|
|
+ RefPhysicalAudioDevice(device);
|
|
|
+ SDL_RunOnMainThread(SDL_AudioDeviceDisconnected_OnMainThread, device, false);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|