Browse Source

fix deadlock on close device

James Zipperer

snd_pcm_drain doesn't always drain when you unplug a usb device.  Use snd_pcm_drop instead
Sam Lantinga 8 years ago
parent
commit
69cf170356
2 changed files with 11 additions and 7 deletions
  1. 8 6
      src/audio/SDL_audio.c
  2. 3 1
      src/audio/alsa/SDL_alsa_audio.c

+ 8 - 6
src/audio/SDL_audio.c

@@ -725,13 +725,15 @@ SDL_RunAudio(void *devicep)
         }
 
         /* !!! FIXME: this should be LockDevice. */
-        SDL_LockMutex(device->mixer_lock);
-        if (SDL_AtomicGet(&device->paused)) {
-            SDL_memset(stream, silence, stream_len);
-        } else {
-            (*callback) (udata, stream, stream_len);
+        if ( SDL_AtomicGet(&device->enabled) ) {
+            SDL_LockMutex(device->mixer_lock);
+            if (SDL_AtomicGet(&device->paused)) {
+                SDL_memset(stream, silence, stream_len);
+            } else {
+                (*callback) (udata, stream, stream_len);
+            }
+            SDL_UnlockMutex(device->mixer_lock);
         }
-        SDL_UnlockMutex(device->mixer_lock);
 
         /* Convert the audio if necessary */
         if (device->convert.needed && SDL_AtomicGet(&device->enabled)) {

+ 3 - 1
src/audio/alsa/SDL_alsa_audio.c

@@ -49,6 +49,7 @@ static snd_pcm_sframes_t (*ALSA_snd_pcm_readi)
 static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
 static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
 static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
+static int (*ALSA_snd_pcm_drop) (snd_pcm_t *);
 static const char *(*ALSA_snd_strerror) (int);
 static size_t(*ALSA_snd_pcm_hw_params_sizeof) (void);
 static size_t(*ALSA_snd_pcm_sw_params_sizeof) (void);
@@ -128,6 +129,7 @@ load_alsa_syms(void)
     SDL_ALSA_SYM(snd_pcm_recover);
     SDL_ALSA_SYM(snd_pcm_prepare);
     SDL_ALSA_SYM(snd_pcm_drain);
+    SDL_ALSA_SYM(snd_pcm_drop);
     SDL_ALSA_SYM(snd_strerror);
     SDL_ALSA_SYM(snd_pcm_hw_params_sizeof);
     SDL_ALSA_SYM(snd_pcm_sw_params_sizeof);
@@ -402,7 +404,7 @@ static void
 ALSA_CloseDevice(_THIS)
 {
     if (this->hidden->pcm_handle) {
-        ALSA_snd_pcm_drain(this->hidden->pcm_handle);
+        ALSA_snd_pcm_drop(this->hidden->pcm_handle);
         ALSA_snd_pcm_close(this->hidden->pcm_handle);
     }
     SDL_free(this->hidden->mixbuf);