audio/alsa: Exit write loop if underlying device is already paused.
authorDoug Nazar <nazard@nazar.ca>
Wed, 7 Apr 2021 08:25:47 +0000 (04:25 -0400)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 8 Apr 2021 07:28:21 +0000 (07:28 +0000)
If the alsasink thread starts the write loop but another thread pauses
the underlying alsa device, the sink thread will endlessly loop.

snd_pcm_writei() will return 0 if the state is SND_PCM_STATE_PAUSED
and the loop will never make any progress.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1097>

ext/alsa/gstalsasink.c
gst-libs/gst/audio/gstaudiosink.c

index e2eca19..26cd1fc 100644 (file)
@@ -1089,6 +1089,10 @@ gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
         goto write_error;
       }
       continue;
+    } else if (err == 0 && alsa->hw_support_pause) {
+      /* We might be already paused, if so, just bail */
+      if (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PAUSED)
+        break;
     }
 
     ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
index bda51fe..d7b26f1 100644 (file)
@@ -254,6 +254,9 @@ audioringbuffer_thread_func (GstAudioRingBuffer * buf)
               GST_DEBUG_FUNCPTR_NAME (writefunc),
               (errno > 1 ? g_strerror (errno) : "unknown"), left, written);
           break;
+        } else if (written == 0 && G_UNLIKELY (g_atomic_int_get (&buf->state) !=
+                GST_AUDIO_RING_BUFFER_STATE_STARTED)) {
+          break;
         }
         left -= written;
         readptr += written;