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