SDL: coreaudio: Fixed assertion when device fails/quits mid-iteration.

From 5735d2b03b1c21699a1a17d736d3d66d82f66e22 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Tue, 8 Aug 2023 23:56:17 -0400
Subject: [PATCH] coreaudio: Fixed assertion when device fails/quits
 mid-iteration.

Fixes #8094.
---
 src/audio/coreaudio/SDL_coreaudio.m | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m
index 5a54396a981a..b96db86b9f71 100644
--- a/src/audio/coreaudio/SDL_coreaudio.m
+++ b/src/audio/coreaudio/SDL_coreaudio.m
@@ -550,8 +550,16 @@ static void OutputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, Audi
     SDL_assert(inBuffer != NULL);  // ...right?
     SDL_assert(device->hidden->current_buffer == NULL);  // shouldn't have anything pending
     device->hidden->current_buffer = inBuffer;
-    SDL_OutputAudioThreadIterate(device);
-    SDL_assert(device->hidden->current_buffer == NULL);  // PlayDevice should have enqueued and cleaned it out.
+    const SDL_bool okay = SDL_OutputAudioThreadIterate(device);
+    SDL_assert((device->hidden->current_buffer == NULL) || !okay);  // PlayDevice should have enqueued and cleaned it out, unless we failed or shutdown.
+
+    // buffer is unexpectedly here? We're probably dying, but try to requeue this buffer with silence.
+    if (device->hidden->current_buffer) {
+        AudioQueueBufferRef current_buffer = device->hidden->current_buffer;
+        device->hidden->current_buffer = NULL;
+        SDL_memset(current_buffer->mAudioData, device->silence_value, (size_t) current_buffer->mAudioDataBytesCapacity);
+        AudioQueueEnqueueBuffer(device->hidden->audioQueue, current_buffer, 0, NULL);
+    }
 }
 
 static int COREAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen)