[alsa-devel] [PATCH] Meter causes freeze when closing audio device

Alistair Buxton a.j.buxton at gmail.com
Mon Mar 6 04:01:47 CET 2017


After adding assert(0); to snd_timer_stop I got the following backtrace:

#0  0x00007ffff730d428 in __GI_raise (sig=sig at entry=6) at
../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff730f02a in __GI_abort () at abort.c:89
#2  0x00007ffff7305bd7 in __assert_fail_base (fmt=<optimised out>,
assertion=assertion at entry=0x7ffff7b9439e "0",
    file=file at entry=0x7ffff7b9e8b9 "timer.c", line=line at entry=918,
    function=function at entry=0x7ffff7b9e9c8 <__PRETTY_FUNCTION__.10913>
"snd_timer_stop") at assert.c:92
#3  0x00007ffff7305c82 in __GI___assert_fail
(assertion=assertion at entry=0x7ffff7b9439e "0",
    file=file at entry=0x7ffff7b9e8b9 "timer.c", line=line at entry=918,
    function=function at entry=0x7ffff7b9e9c8 <__PRETTY_FUNCTION__.10913>
"snd_timer_stop") at assert.c:101
#4  0x00007ffff7b64503 in snd_timer_stop (timer=<optimised out>) at timer.c:918
#5  0x00007ffff7b5158d in snd_pcm_dmix_sync_ptr0
(pcm=pcm at entry=0x622de0, slave_hw_ptr=<optimised out>)
    at pcm_dmix.c:421
#6  0x00007ffff7b51aac in snd_pcm_dmix_status (pcm=0x622de0,
status=0x7ffff6af1e80) at pcm_dmix.c:496
#7  0x00007ffff7b18f11 in snd_pcm_status (pcm=pcm at entry=0x622de0,
status=status at entry=0x7ffff6af1e80) at pcm.c:977
#8  0x00007ffff7b48bc0 in snd_pcm_meter_thread (data=0x622940) at
pcm_meter.c:200
#9  0x00007ffff76a86ba in start_thread (arg=0x7ffff6af2700) at
pthread_create.c:333
#10 0x00007ffff73de82d in clone () at
../sysdeps/unix/sysv/linux/x86_64/clone.S:109

So the meter thread is indirectly stopping the timer while the main
thread is trying to poll it.

The following patch avoids this issue. Is it the right way to fix it?

>From f21cd1ec8245198279cc2ad606041f7f59e8341d Mon Sep 17 00:00:00 2001
From: Alistair Buxton <a.j.buxton at gmail.com>
Date: Mon, 6 Mar 2017 02:50:35 +0000
Subject: [PATCH] pcm: meter: Put a mutex around slave drain to prevent
 deadlock

The meter thread calls _status on its slave. If this happens while
dmix is draining, the timer will be stopped, causing the main thread
 to get stuck in poll().
---
 src/pcm/pcm_meter.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c
index d71af7a..43a25fc 100644
--- a/src/pcm/pcm_meter.c
+++ b/src/pcm/pcm_meter.c
@@ -324,6 +324,18 @@ static int snd_pcm_meter_start(snd_pcm_t *pcm)
 	return err;
 }

+static int snd_pcm_meter_drain(snd_pcm_t *pcm)
+{
+	snd_pcm_meter_t *meter = pcm->private_data;
+	int err;
+	pthread_mutex_lock(&meter->running_mutex);
+	err = snd_pcm_drain(meter->gen.slave);
+	if (err >= 0)
+		pthread_cond_signal(&meter->running_cond);
+	pthread_mutex_unlock(&meter->running_mutex);
+	return err;
+}
+
 static snd_pcm_sframes_t snd_pcm_meter_rewind(snd_pcm_t *pcm,
snd_pcm_uframes_t frames)
 {
 	snd_pcm_meter_t *meter = pcm->private_data;
@@ -530,7 +542,7 @@ static const snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
 	.reset = snd_pcm_meter_reset,
 	.start = snd_pcm_meter_start,
 	.drop = snd_pcm_generic_drop,
-	.drain = snd_pcm_generic_drain,
+	.drain = snd_pcm_meter_drain,
 	.pause = snd_pcm_generic_pause,
 	.rewindable = snd_pcm_generic_rewindable,
 	.rewind = snd_pcm_meter_rewind,
-- 
2.7.4



-- 
Alistair Buxton
a.j.buxton at gmail.com


More information about the Alsa-devel mailing list