From 29041c522071172af2c6bf086b3a0c19510a6660 Mon Sep 17 00:00:00 2001 From: "sylvain.bertrand@gmail.com" Date: Tue, 28 Apr 2020 12:09:18 +0000 Subject: [PATCH] fix infinite draining of the rate plugin in SND_PCM_NONBLOCK mode The draining function of the rate plugin does not handle properly the SND_PCM_NONBLOCK case. It can write data to the slave plugin each time the function is called, but does not update its internal state in order to reach a stopping condition. Use a last_commit_ptr workaround to reach such condition. Signed-off-by: Sylvain BERTRAND Signed-off-by: Jaroslav Kysela --- src/pcm/pcm_rate.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 21611f62..4f99a95b 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -1051,6 +1051,7 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm) /* commit the remaining fraction (if any) */ snd_pcm_uframes_t size, ofs, saved_avail_min; snd_pcm_sw_params_t sw_params; + int commit_err; __snd_pcm_lock(pcm); /* temporarily set avail_min to one */ @@ -1079,14 +1080,29 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm) if (! spsize) break; } - snd_pcm_rate_commit_area(pcm, rate, ofs, + commit_err = snd_pcm_rate_commit_area(pcm, rate, ofs, psize, spsize); + if (commit_err == 1) { + rate->last_commit_ptr += psize; + if (rate->last_commit_ptr >= pcm->boundary) + rate->last_commit_ptr = 0; + } else if (commit_err == 0) { + if (pcm->mode & SND_PCM_NONBLOCK != 0) { + commit_err = -EAGAIN; + break; + } + continue; + } else + break; + ofs = (ofs + psize) % pcm->buffer_size; size -= psize; } sw_params.avail_min = saved_avail_min; snd_pcm_sw_params(rate->gen.slave, &sw_params); __snd_pcm_unlock(pcm); + if (commit_err < 0) + return commit_err; } return snd_pcm_drain(rate->gen.slave); } -- 2.47.1