fix(pulse): Hanging during connection setup (#2709)

If context_state_callback is called before we call
pa_threaded_mainloop_wait in the main thread, the signal is lost and we
wait forever.

Fixes #2707
Ref #2699
Ref #2697
This commit is contained in:
Patrick Ziegler 2022-05-04 08:58:53 +02:00 committed by GitHub
parent efbd8e394f
commit f653c3a738
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 1 deletions

View File

@ -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

View File

@ -2,6 +2,7 @@
#include <pulse/pulseaudio.h>
#include <atomic>
#include <queue>
#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{};

View File

@ -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");
/*
* 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;