Query about xrun on usb/pcm

Carl Hetherington lists at carlh.net
Mon Nov 28 23:51:55 CET 2022


Hi Takashi,

Thank you for your continued attention with this!

[snip]

> > I'll see if can apply a similar fix to this case, though to my naive
> > eyes it looks a little trickier as the xrun is found in the snd_pcm
> > code rather than the USB code.  Any suggestions most welcome!
>
> OK, then it's a bit different problem, and not so trivial to fix in
> the kernel side alone, I'm afraid.  Basically it's a race between
> start and stop of two streams.  The key point is that, for stopping a
> (USB) stream, a sync-stop operation is needed, and this can't be
> performed at the PCM trigger itself (which is an atomic operation).
> So, the kernel trigger may at most return an error there.
>
> I assume that it's from snd_usb_endpoint_start() and it returning
> -EPIPE error.  If so, we may change the PCM core code to set the PCM
> state again XRUN in such an error case, so that application may repeat
> the standard recovery process.  Something like below.

Thanks for the suggestion.  I experimented a little with this, but I
think the problem I'm seeing is that (even if the application knows it
should retry the snd_pcm_prepare() step) we still end up with an endpoint
in EP_STATE_STOPPING while the corresponding stop_operating flag is 0.

This means that snd_pcm_sync_stop will never call the USB sync_stop
handler, which AFAICS is the only way (?) the endpoint can get back to
EP_STATE_STOPPED.

In my error case, the code in snd_pcm_sync_stop sets stop_operating to
false (perhaps assuming that substream->ops->sync_stop will "succeed"
in setting any STOPPING endpoints to STOPPED) but then this doesn't
happen because of this xrun that arrives halfway through the sync_stop
operation.

I experimented with removing the check at the top of snd_pcm_sync_stop,
so that we enter the if body regardless of
substream->runtime->stop_operating, and making my application retry
snd_pcm_prepare() if it fails with -EPIPE, and this seems to "fix" my
problem.  Obviously this causes more (unnecessary) calls to the
sync_stop() entry point...

I'd be grateful of any thoughts you have about that.

Kind regards,
Carl


More information about the Alsa-devel mailing list