From 485ed0b1564ba27714e24e1ee5aff05295862f92 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 26 Apr 2018 16:12:32 +0200 Subject: [PATCH] output/alsa: make the "active" attribute thread-safe --- src/output/plugins/AlsaOutputPlugin.cxx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index 5eae7928f..70d9360d7 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -123,8 +123,7 @@ class AlsaOutput final * After Open(), has this output been activated by a Play() * command? * - * This attribute is not thread-safe. It is only used by the - * client thread (the thread which calls AudioOutput public methods). + * Protected by #mutex. */ bool active; @@ -162,7 +161,7 @@ class AlsaOutput final Alsa::PeriodBuffer period_buffer; /** - * Protects #cond, #error, #drain. + * Protects #cond, #error, #active, #drain. */ mutable Mutex mutex; @@ -228,6 +227,12 @@ private: #endif ); + gcc_pure + bool LockIsActive() const noexcept { + const std::lock_guard lock(mutex); + return active; + } + /** * Activate the output by registering the sockets in the * #EventLoop. Before calling this, filling the ring buffer @@ -784,7 +789,7 @@ AlsaOutput::CancelInternal() noexcept void AlsaOutput::Cancel() noexcept { - if (!active) { + if (!LockIsActive()) { /* early cancel, quick code path without thread synchronization */ @@ -880,6 +885,9 @@ AlsaOutput::DispatchSockets() noexcept try { { const std::lock_guard lock(mutex); + + assert(active); + if (drain) { { ScopeUnlock unlock(mutex);