fix(alsa): correct handling of capture overruns#1122
Open
roderickvd wants to merge 2 commits intomasterfrom
Open
fix(alsa): correct handling of capture overruns#1122roderickvd wants to merge 2 commits intomasterfrom
roderickvd wants to merge 2 commits intomasterfrom
Conversation
POLLERR from snd_pcm_poll_descriptors_revents() signals an xrun but was being returned as a BackendSpecificError, causing the poll loop to spin indefinitely. It now falls through to avail(), which returns EPIPE and triggers xrun recovery. Capture streams also require an explicit snd_pcm_start() after snd_pcm_prepare() to re-enter SND_PCM_STATE_RUNNING; without it the stream stalled in PREPARED and poll() timed out repeatedly. POLLHUP/POLLNVAL now stop the stream with StreamError::DeviceNotAvailable instead of looping and poll() returning 0 (timeout/spurious) is now treated as Continue rather than an error. Fixes #730
There was a problem hiding this comment.
Pull request overview
Fixes ALSA stream worker behavior around capture overruns/disconnects by preventing poll-loop spins and ensuring capture restarts correctly after xrun recovery.
Changes:
- Treat
poll()returning0(timeout/spurious wakeup) asContinuerather than an error. - Handle
POLLHUP/POLLNVALasStreamError::DeviceNotAvailableand treatPOLLERRas xrun (fall through toavail()/EPIPE-> recovery). - After xrun recovery on capture, call
snd_pcm_start()followingsnd_pcm_prepare()to re-enterRUNNING. - Update changelog entries for ALSA behavior fixes.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/host/alsa/mod.rs |
Adjusts ALSA poll/event handling and capture xrun recovery to avoid infinite loops and stalls. |
CHANGELOG.md |
Documents ALSA behavior changes/fixes for overruns and disconnections. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Member
Author
|
The Copilot review seems a valid concern and a pre-existing fragility. I'll think about how to address it. |
TriggerReceiver is now wrapped in Arc and a clone is stored in Stream alongside the sender. Worker threads take their own Arc clone, so dropping the worker no longer closes the read end of the pipe. This means wakeup() in Stream::drop() always writes to an open pipe, even when the worker exited early due to a device error, eliminating the SIGPIPE that would otherwise be raised.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
POLLERRfromsnd_pcm_poll_descriptors_revents()signals an xrun but was being returned as aBackendSpecificError, causing the poll loop to spin indefinitely. It now falls through toavail(), which returnsEPIPEand triggers xrun recovery.Capture streams also require an explicit
snd_pcm_start()aftersnd_pcm_prepare()to re-enterSND_PCM_STATE_RUNNING; without it the stream stalled inPREPAREDandpoll()timed out repeatedly.POLLHUP/POLLNVALnow stop the stream withStreamError::DeviceNotAvailableinstead of looping andpoll()returning 0 (timeout/spurious) is now treated asContinuerather than an error.Fixes #730