lib/alsa/NonBlock: throw exception on error

Avoid another potential deadlock: if no file descriptors are
registered, our non-blocking ALSA code cannot ever work.
This commit is contained in:
Max Kellermann 2017-11-14 21:06:17 +01:00
parent e0f777d4eb
commit 7d579e7400
3 changed files with 24 additions and 7 deletions

View File

@ -20,22 +20,31 @@
#include "config.h"
#include "NonBlock.hxx"
#include "event/MultiSocketMonitor.hxx"
#include "util/RuntimeError.hxx"
std::chrono::steady_clock::duration
PrepareAlsaPcmSockets(MultiSocketMonitor &m, snd_pcm_t *pcm,
ReusableArray<pollfd> &pfd_buffer) noexcept
ReusableArray<pollfd> &pfd_buffer)
{
int count = snd_pcm_poll_descriptors_count(pcm);
if (count <= 0) {
m.ClearSocketList();
return std::chrono::steady_clock::duration(-1);
if (count == 0)
throw std::runtime_error("snd_pcm_poll_descriptors_count() failed");
else
throw FormatRuntimeError("snd_pcm_poll_descriptors_count() failed: %s",
snd_strerror(-count));
}
struct pollfd *pfds = pfd_buffer.Get(count);
count = snd_pcm_poll_descriptors(pcm, pfds, count);
if (count < 0)
count = 0;
if (count <= 0) {
if (count == 0)
throw std::runtime_error("snd_pcm_poll_descriptors() failed");
else
throw FormatRuntimeError("snd_pcm_poll_descriptors() failed: %s",
snd_strerror(-count));
}
m.ReplaceSocketList(pfds, count);
return std::chrono::steady_clock::duration(-1);

View File

@ -33,10 +33,12 @@ class MultiSocketMonitor;
* Update #MultiSocketMonitor's socket list from
* snd_pcm_poll_descriptors(). To be called from
* MultiSocketMonitor::PrepareSockets().
*
* Throws exception on error.
*/
std::chrono::steady_clock::duration
PrepareAlsaPcmSockets(MultiSocketMonitor &m, snd_pcm_t *pcm,
ReusableArray<pollfd> &pfd_buffer) noexcept;
ReusableArray<pollfd> &pfd_buffer);
/**
* Update #MultiSocketMonitor's socket list from

View File

@ -815,7 +815,13 @@ AlsaOutput::PrepareSockets() noexcept
return std::chrono::steady_clock::duration(-1);
}
return PrepareAlsaPcmSockets(*this, pcm, pfd_buffer);
try {
return PrepareAlsaPcmSockets(*this, pcm, pfd_buffer);
} catch (...) {
ClearSocketList();
LockCaughtError();
return std::chrono::steady_clock::duration(-1);
}
}
void