From a6b7ac50ef527947c0c9ab3deaba156bb63b266b Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 18 Nov 2025 01:46:29 +0200 Subject: [PATCH] Eliminate hang completely by making ALSA interruption immediate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Previous fix reduced but didn't eliminate the hang when switching audio sources. The C layer was still blocking on snd_pcm_readi()/snd_pcm_writei() while holding the mutex, preventing cleanup from proceeding. Solution: Call snd_pcm_drop() BEFORE acquiring the mutex in close functions. This immediately interrupts any blocking ALSA read/write operations, causing them to return with -EBADFD or -ESTRPIPE. The sequence is now: 1. Set stop_requested flag 2. Call snd_pcm_drop() to interrupt blocking I/O (no mutex needed - thread-safe) 3. Acquire mutex for cleanup 4. Close handles and free resources 5. Release mutex This makes audio source switching instantaneous with zero hang. Changes: - jetkvm_audio_capture_close(): Drop PCM before mutex - jetkvm_audio_playback_close(): Drop PCM before mutex Tested: USB↔HDMI switching now happens instantly with no delay. --- internal/audio/c/audio.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/internal/audio/c/audio.c b/internal/audio/c/audio.c index f078dcb3..6572a027 100644 --- a/internal/audio/c/audio.c +++ b/internal/audio/c/audio.c @@ -776,7 +776,13 @@ void jetkvm_audio_playback_close() { return; } - // Acquire mutex to prevent concurrent write operations + // Drop PCM stream BEFORE acquiring mutex to interrupt any blocking writes + // snd_pcm_drop() is thread-safe and will cause snd_pcm_writei() to return immediately + if (pcm_playback_handle) { + snd_pcm_drop(pcm_playback_handle); + } + + // Now acquire mutex for cleanup pthread_mutex_lock(&playback_mutex); if (decoder) { @@ -784,7 +790,6 @@ void jetkvm_audio_playback_close() { decoder = NULL; } if (pcm_playback_handle) { - snd_pcm_drop(pcm_playback_handle); snd_pcm_close(pcm_playback_handle); pcm_playback_handle = NULL; } @@ -807,11 +812,16 @@ void jetkvm_audio_capture_close() { return; } - // Acquire mutex to prevent concurrent read operations + // Drop PCM stream BEFORE acquiring mutex to interrupt any blocking reads + // snd_pcm_drop() is thread-safe and will cause snd_pcm_readi() to return immediately + if (pcm_capture_handle) { + snd_pcm_drop(pcm_capture_handle); + } + + // Now acquire mutex for cleanup pthread_mutex_lock(&capture_mutex); if (pcm_capture_handle) { - snd_pcm_drop(pcm_capture_handle); snd_pcm_close(pcm_capture_handle); pcm_capture_handle = NULL; }