output/alsa: fix deadlock bug
After UnlockActivate() returns, we not only need to check for errors, but also for more room in the ring buffer. If we don't check the ring buffer, it may be drained already, and the cond.wait() call will never finish. Closes #151
This commit is contained in:
parent
1040b85785
commit
febd1ad09c
@ -232,13 +232,17 @@ private:
|
||||
/**
|
||||
* Wrapper for Activate() which unlocks our mutex. Call this
|
||||
* if you're holding the mutex.
|
||||
*
|
||||
* @return true if Activate() was called, false if the mutex
|
||||
* was never unlocked
|
||||
*/
|
||||
void UnlockActivate() noexcept {
|
||||
bool UnlockActivate() noexcept {
|
||||
if (active)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const ScopeUnlock unlock(mutex);
|
||||
Activate();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClearRingBuffer() noexcept {
|
||||
@ -784,13 +788,12 @@ AlsaOutput::Play(const void *chunk, size_t size)
|
||||
/* now that the ring_buffer is full, we can activate
|
||||
the socket handlers to trigger the first
|
||||
snd_pcm_writei() */
|
||||
UnlockActivate();
|
||||
|
||||
/* check the error again, because a new one may have
|
||||
been set while our mutex was unlocked in
|
||||
UnlockActivate() */
|
||||
if (error)
|
||||
std::rethrow_exception(error);
|
||||
if (UnlockActivate())
|
||||
/* since everything may have changed while the
|
||||
mutex was unlocked, we need to skip the
|
||||
cond.wait() call below and check the new
|
||||
status */
|
||||
continue;
|
||||
|
||||
/* wait for the DispatchSockets() to make room in the
|
||||
ring_buffer */
|
||||
|
Loading…
Reference in New Issue
Block a user