[alsa-devel] Bug in snd_pcm_ioplug_avail_update()?

Takashi Iwai tiwai at suse.de
Tue Jul 17 07:04:02 CEST 2018


On Tue, 17 Jul 2018 01:53:36 +0200,
Rob Duncan wrote:
> 
> 
> At 11:38 on Mon, Jul 16 2018, Takashi wrote:
> 
> > Yeah, this looks like a bug.  The code there supposed to copy the
> > whole data that is available, while snd_pcm_mmap_begin() gives the
> > range only for a single copy action, so it won't fill if the region to
> > fill is split across the buffer boundary.
> >
> > I guess we need some open-code there to achieve the whole data copy.
> > The avail value from snd_pcm_mmap_avail() can be moved before the
> > action, so that we can avoid to calculate this twice.
> >
> > If you have already some fix patch, it'd be helpful.  Otherwise I'll
> > fix it up some time later.
> 
> How about this?
> 
> Rob.
> 
> >From 467766fc0bd2fb0981d699d018114fa348ddc6ac Mon Sep 17 00:00:00 2001
> From: Rob Duncan <rduncan at teslamotors.com>
> Date: Mon, 16 Jul 2018 16:35:23 -0700
> Subject: [PATCH] pcm: ioplug: Transfer all available data
> 
> The snd_pcm_mmap_begin() call returns the amount of contiguous data,
> which is less than the total available if it wraps around the buffer
> boundary.
> 
> If we don't handle this split we leave stale data in the buffer that
> should have been overwritten, as well as unread data in the io_plugin
> that gets transferred on a subsequent call at the wrong offset.
> 
> Signed-off-by: Rob Duncan <rduncan at teslamotors.com>

The code change is similar as what I had in my mind, but...


> ---
>  src/pcm/pcm_ioplug.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
> index 6d52c27b..90e55d0a 100644
> --- a/src/pcm/pcm_ioplug.c
> +++ b/src/pcm/pcm_ioplug.c
> @@ -713,6 +713,8 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
>  	ioplug_priv_t *io = pcm->private_data;
>  	snd_pcm_uframes_t avail;
>  
> +	avail = snd_pcm_mmap_avail(pcm);

This call should be put after the hwptr update.  That is...


> +
>  	snd_pcm_ioplug_hw_ptr_update(pcm);
>  	if (io->data->state == SND_PCM_STATE_XRUN)
>  		return -EPIPE;

... put here.

In addition:

> @@ -728,9 +730,15 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
>  			result = io->data->callback->transfer(io->data, areas, offset, size);
>  			if (result < 0)
>  				return result;
> +
> +			if (size < avail) {
> +				result = io->data->callback->transfer(io->data, areas,
> +								      0, avail - size);
> +				if (result < 0)
> +					return result;
> +			}

Please give a short comment about the buffer boundary wrap for
readers.


Thanks!

Takashi


More information about the Alsa-devel mailing list