Repository navigation
Conversation
When outputLoop stops on an error (snd_pcm_recover failing, a reader error or an unsupported format), it marked the output closed without closing the PCM handle. Close() returns early for a closed output, so the handle stayed open until the process exited: every later open of the device failed with "Device or resource busy", for go-librespot and for any other program wanting the same device. Seen with a USB DAC returning EIO during playback: after that, every track and every transfer failed with snd_pcm_open: Device or resource busy until go-librespot was restarted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If snd_pcm_close failed after EOF, outputLoop unlocked out.lock in the error branch and again right after it, which panics with "sync: unlock of unlocked mutex". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
When
outputLoopstops on an error, it marks the output closed without closing the PCM handle.Close()returns early for a closed output, so the handle stays open until the process exits, and every later open of the same device fails withDevice or resource busy, for go-librespot itself and for any other program that wants the device.What happens
Seen with a USB DAC that returned
EIOduring playback (no disconnect in the kernel log):After that, every next track and every transfer to the device failed the same way, and another player on the same machine couldn't open the DAC either, until go-librespot was restarted.
The three error branches in
outputLoop(snd_pcm_recoverfailing, a reader error, an unsupported format) setout.closed = trueand return. The player then callsout.Close(), which seesclosedand skipssnd_pcm_close.Fix
closePcmAfterError, called with the lock held).snd_pcm_closefails at EOF,out.lockwas unlocked twice, which panics.Tested
On a Raspberry Pi 4 (aarch64) with a USB DAC, driving
output.NewOutputdirectly with a silent reader:snd_pcm_writeimade to return-EIOonce (LD_PRELOADshim), sosnd_pcm_recoverfails without the device going away. Before: afterClose()the PCM fd is still open andaplayon the device getsDevice or resource busy. After: no PCM fd left,aplayplays.snd_pcm_recover: No such device). Before: the fd of the removed device stays open. After: it's closed.🤖 Generated with Claude Code