wasapi: Don't proxy device disconnect to the WASAPI management thread.

It gets proxied to the main thread, now.

Fixes deadlocks when unplugging a playing USB audio device.
This commit is contained in:
Ryan C. Gordon
2025-09-26 14:10:16 -04:00
parent cd9919dc51
commit e528d5bd9f

View File

@@ -164,21 +164,10 @@ bool WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, b
return true; // successfully added (and possibly executed)! return true; // successfully added (and possibly executed)!
} }
static bool mgmtthrtask_AudioDeviceDisconnected(void *userdata)
{
SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
SDL_AudioDeviceDisconnected(device);
UnrefPhysicalAudioDevice(device); // make sure this lived until the task completes.
return true;
}
static void AudioDeviceDisconnected(SDL_AudioDevice *device) static void AudioDeviceDisconnected(SDL_AudioDevice *device)
{ {
// don't wait on this, IMMDevice's own thread needs to return or everything will deadlock. WASAPI_DisconnectDevice(device);
if (device) {
RefPhysicalAudioDevice(device); // make sure this lives until the task completes.
WASAPI_ProxyToManagementThread(mgmtthrtask_AudioDeviceDisconnected, device, NULL);
}
} }
static bool mgmtthrtask_DefaultAudioDeviceChanged(void *userdata) static bool mgmtthrtask_DefaultAudioDeviceChanged(void *userdata)
@@ -351,19 +340,11 @@ static void WASAPI_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDe
WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, &data, &rc); WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, &data, &rc);
} }
static bool mgmtthrtask_DisconnectDevice(void *userdata)
{
SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
SDL_AudioDeviceDisconnected(device);
UnrefPhysicalAudioDevice(device);
return true;
}
void WASAPI_DisconnectDevice(SDL_AudioDevice *device) void WASAPI_DisconnectDevice(SDL_AudioDevice *device)
{ {
if (SDL_CompareAndSwapAtomicInt(&device->hidden->device_disconnecting, 0, 1)) { // don't block in here; IMMDevice's own thread needs to return or everything will deadlock.
RefPhysicalAudioDevice(device); // will unref when the task ends. if (device->hidden && SDL_CompareAndSwapAtomicInt(&device->hidden->device_disconnecting, 0, 1)) {
WASAPI_ProxyToManagementThread(mgmtthrtask_DisconnectDevice, device, NULL); SDL_AudioDeviceDisconnected(device); // this proxies the work to the main thread now, so no point in proxying to the management thread.
} }
} }