SDL: Clamp the audio drain delay to 100 ms (6db23)

From 6db23faa44e8c35dc6c6dd58ea5b330f9f3c89cd Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 2 Nov 2025 09:50:16 -0800
Subject: [PATCH] Clamp the audio drain delay to 100 ms

Fixes https://github.com/libsdl-org/SDL/issues/9829

(cherry picked from commit 08826230923dfb70e4558a41179ac0744e69fdb8)
---
 src/audio/SDL_audio.c           | 11 ++++++++---
 src/audio/alsa/SDL_alsa_audio.c |  3 +++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 1ab847aa490ea..75e89797d4b33 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -678,6 +678,7 @@ static int SDLCALL SDL_RunAudio(void *userdata)
     int data_len = 0;
     Uint8 *data;
     Uint8 *device_buf_keepsafe = NULL;
+    Uint32 delay;
 
     SDL_assert(!device->iscapture);
 
@@ -761,7 +762,7 @@ static int SDLCALL SDL_RunAudio(void *userdata)
                 SDL_assert((got <= 0) || (got == device->spec.size));
 
                 if (data == NULL) { /* device is having issues... */
-                    const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
+                    delay = ((device->spec.samples * 1000) / device->spec.freq);
                     SDL_Delay(delay); /* wait for as long as this buffer would have played. Maybe device recovers later? */
                 } else {
                     if (got != device->spec.size) {
@@ -781,7 +782,7 @@ static int SDLCALL SDL_RunAudio(void *userdata)
             }
         } else if (data == device->work_buffer) {
             /* nothing to do; pause like we queued a buffer to play. */
-            const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
+            delay = ((device->spec.samples * 1000) / device->spec.freq);
             SDL_Delay(delay);
         } else { /* writing directly to the device. */
             /* queue this buffer and wait for it to finish playing. */
@@ -791,7 +792,11 @@ static int SDLCALL SDL_RunAudio(void *userdata)
     }
 
     /* Wait for the audio to drain. */
-    SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
+    delay = ((device->spec.samples * 1000) / device->spec.freq) * 2;
+    if (delay > 100) {
+        delay = 100;
+    }
+    SDL_Delay(delay);
 
     current_audio.impl.ThreadDeinit(device);
 
diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c
index b7d3edfaeb132..120244ab0060a 100644
--- a/src/audio/alsa/SDL_alsa_audio.c
+++ b/src/audio/alsa/SDL_alsa_audio.c
@@ -472,6 +472,9 @@ static void ALSA_CloseDevice(_THIS)
            ALSA_snd_pcm_drop() can hang, so don't use that.
          */
         Uint32 delay = ((this->spec.samples * 1000) / this->spec.freq) * 2;
+        if (delay > 100) {
+            delay = 100;
+        }
         SDL_Delay(delay);
 
         ALSA_snd_pcm_close(this->hidden->pcm_handle);