From d16f76e3d46cabf281bc540c29750806d27fcee6 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sun, 5 Jan 2025 20:54:15 -0500
Subject: [PATCH] wasapi: Don't crash/hang if transitioning to/from a Remote
Desktop Connection.
Fixes #9673.
---
src/audio/wasapi/SDL_wasapi.c | 18 ++++++++++++------
src/audio/wasapi/SDL_wasapi.h | 1 +
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c
index a7dbda97c96eb..71eb3291950f0 100644
--- a/src/audio/wasapi/SDL_wasapi.c
+++ b/src/audio/wasapi/SDL_wasapi.c
@@ -353,14 +353,18 @@ static void WASAPI_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDe
static bool mgmtthrtask_DisconnectDevice(void *userdata)
{
- SDL_AudioDeviceDisconnected((SDL_AudioDevice *)userdata);
+ SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
+ SDL_AudioDeviceDisconnected(device);
+ UnrefPhysicalAudioDevice(device);
return true;
}
void WASAPI_DisconnectDevice(SDL_AudioDevice *device)
{
- bool rc; // block on this; don't disconnect while holding the device lock!
- WASAPI_ProxyToManagementThread(mgmtthrtask_DisconnectDevice, device, &rc);
+ if (SDL_CompareAndSwapAtomicInt(&device->hidden->device_disconnecting, 0, 1)) {
+ RefPhysicalAudioDevice(device); // will unref when the task ends.
+ WASAPI_ProxyToManagementThread(mgmtthrtask_DisconnectDevice, device, NULL);
+ }
}
static bool WasapiFailed(SDL_AudioDevice *device, const HRESULT err)
@@ -503,8 +507,10 @@ static bool RecoverWasapiDevice(SDL_AudioDevice *device)
static bool RecoverWasapiIfLost(SDL_AudioDevice *device)
{
if (SDL_GetAtomicInt(&device->shutdown)) {
- return false; // already failed.
- } else if (device->hidden->device_dead) { // had a fatal error elsewhere, clean up and quit
+ return false; // closing, stop trying.
+ } else if (SDL_GetAtomicInt(&device->hidden->device_disconnecting)) {
+ return false; // failing via the WASAPI management thread, stop trying.
+ } else if (device->hidden->device_dead) { // had a fatal error elsewhere, clean up and quit
IAudioClient_Stop(device->hidden->client);
WASAPI_DisconnectDevice(device);
SDL_assert(SDL_GetAtomicInt(&device->shutdown)); // so we don't come back through here.
@@ -541,7 +547,7 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
static bool WASAPI_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
{
- if (device->hidden->render) { // definitely activated?
+ if (device->hidden->render && !SDL_GetAtomicInt(&device->hidden->device_disconnecting)) { // definitely activated?
// WasapiFailed() will mark the device for reacquisition or removal elsewhere.
WasapiFailed(device, IAudioRenderClient_ReleaseBuffer(device->hidden->render, device->sample_frames, 0));
}
diff --git a/src/audio/wasapi/SDL_wasapi.h b/src/audio/wasapi/SDL_wasapi.h
index ad046008fcbba..5e528dc7850e4 100644
--- a/src/audio/wasapi/SDL_wasapi.h
+++ b/src/audio/wasapi/SDL_wasapi.h
@@ -40,6 +40,7 @@ struct SDL_PrivateAudioData
HANDLE task;
bool coinitialized;
int framesize;
+ SDL_AtomicInt device_disconnecting;
bool device_lost;
bool device_dead;
};