diff --git a/CHANGELOG.md b/CHANGELOG.md index c3ee2e7b..8aa1c047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ipc: Polybar failing to open IPC channel after another user already ran polybar, if `XDG_RUNTIME_DIR` is not set ([`#2683`](https://github.com/polybar/polybar/issues/2683), [`#2684`](https://github.com/polybar/polybar/pull/2684)) - No overlines/underlines being drawn when using offsets ([`#2685`](https://github.com/polybar/polybar/pull/2685)) - Update struts (`_NET_WM_STRUT_PARTIAL`) when hiding the bar ([`#2702`](https://github.com/polybar/polybar/pull/2702)) +- `internal/pulseaudio`: Hanging during startup ([`#2707`](https://github.com/polybar/polybar/issues/2707), [`#2709`](https://github.com/polybar/polybar/pull/2709)) ## [3.6.2] - 2022-04-03 ### Fixed diff --git a/include/adapters/pulseaudio.hpp b/include/adapters/pulseaudio.hpp index a5d23426..1ee10b52 100644 --- a/include/adapters/pulseaudio.hpp +++ b/include/adapters/pulseaudio.hpp @@ -2,6 +2,7 @@ #include +#include #include #include "common.hpp" @@ -58,6 +59,11 @@ class pulseaudio { const logger& m_log; + /** + * Has context_state_callback signalled the mainloop during connection. + */ + std::atomic_bool m_state_callback_signal{false}; + // used for temporary callback results int success{0}; pa_cvolume cv{}; diff --git a/src/adapters/pulseaudio.cpp b/src/adapters/pulseaudio.cpp index 1a6a15b8..8404cceb 100644 --- a/src/adapters/pulseaudio.cpp +++ b/src/adapters/pulseaudio.cpp @@ -24,6 +24,8 @@ pulseaudio::pulseaudio(const logger& logger, string&& sink_name, bool max_volume pa_context_set_state_callback(m_context, context_state_callback, this); + m_state_callback_signal = false; + if (pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0) { pa_context_disconnect(m_context); pa_context_unref(m_context); @@ -42,7 +44,17 @@ pulseaudio::pulseaudio(const logger& logger, string&& sink_name, bool max_volume m_log.trace("pulseaudio: started mainloop"); - pa_threaded_mainloop_wait(m_mainloop); + /* + * Only wait for signal from the context state callback, if it has not + * already signalled the mainloop since pa_context_connect was called, + * otherwise, we would wait forever. + * + * The while loop ensures spurious wakeups are handled. + */ + while (!m_state_callback_signal) { + pa_threaded_mainloop_wait(m_mainloop); + } + if (pa_context_get_state(m_context) != PA_CONTEXT_READY) { pa_threaded_mainloop_unlock(m_mainloop); pa_threaded_mainloop_stop(m_mainloop); @@ -310,6 +322,7 @@ void pulseaudio::context_state_callback(pa_context* context, void* userdata) { case PA_CONTEXT_READY: case PA_CONTEXT_TERMINATED: case PA_CONTEXT_FAILED: + This->m_state_callback_signal = true; pa_threaded_mainloop_signal(This->m_mainloop, 0); break;