Merge pull request #4888 from Alexays/copilot/fix-waybar-deadlock-issue

[WIP] Fix waybar responsiveness and interaction issues
This commit is contained in:
Alexis Rouillard
2026-02-28 15:29:02 +01:00
committed by GitHub
2 changed files with 29 additions and 6 deletions

View File

@@ -54,6 +54,15 @@ waybar::modules::Wireplumber::Wireplumber(const std::string& id, const Json::Val
waybar::modules::Wireplumber::~Wireplumber() { waybar::modules::Wireplumber::~Wireplumber() {
waybar::modules::Wireplumber::modules.remove(this); waybar::modules::Wireplumber::modules.remove(this);
if (mixer_api_ != nullptr) {
g_signal_handlers_disconnect_by_data(mixer_api_, this);
}
if (def_nodes_api_ != nullptr) {
g_signal_handlers_disconnect_by_data(def_nodes_api_, this);
}
if (om_ != nullptr) {
g_signal_handlers_disconnect_by_data(om_, this);
}
wp_core_disconnect(wp_core_); wp_core_disconnect(wp_core_);
g_clear_pointer(&apis_, g_ptr_array_unref); g_clear_pointer(&apis_, g_ptr_array_unref);
g_clear_object(&om_); g_clear_object(&om_);
@@ -528,6 +537,7 @@ bool waybar::modules::Wireplumber::handleScroll(GdkEventScroll* e) {
GVariant* variant = g_variant_new_double(newVol); GVariant* variant = g_variant_new_double(newVol);
gboolean ret; gboolean ret;
g_signal_emit_by_name(mixer_api_, "set-volume", node_id_, variant, &ret); g_signal_emit_by_name(mixer_api_, "set-volume", node_id_, variant, &ret);
g_variant_unref(variant);
} }
return true; return true;
} }

View File

@@ -40,12 +40,16 @@ AudioBackend::AudioBackend(std::function<void()> on_updated_cb, private_construc
} }
AudioBackend::~AudioBackend() { AudioBackend::~AudioBackend() {
if (context_ != nullptr) {
pa_context_disconnect(context_);
}
if (mainloop_ != nullptr) { if (mainloop_ != nullptr) {
mainloop_api_->quit(mainloop_api_, 0); // Lock the mainloop so we can safely disconnect the context.
// This must be done before stopping the thread.
pa_threaded_mainloop_lock(mainloop_);
if (context_ != nullptr) {
pa_context_disconnect(context_);
pa_context_unref(context_);
context_ = nullptr;
}
pa_threaded_mainloop_unlock(mainloop_);
pa_threaded_mainloop_stop(mainloop_); pa_threaded_mainloop_stop(mainloop_);
pa_threaded_mainloop_free(mainloop_); pa_threaded_mainloop_free(mainloop_);
} }
@@ -73,7 +77,14 @@ void AudioBackend::contextStateCb(pa_context* c, void* data) {
auto* backend = static_cast<AudioBackend*>(data); auto* backend = static_cast<AudioBackend*>(data);
switch (pa_context_get_state(c)) { switch (pa_context_get_state(c)) {
case PA_CONTEXT_TERMINATED: case PA_CONTEXT_TERMINATED:
backend->mainloop_api_->quit(backend->mainloop_api_, 0); // Only quit the mainloop if this is still the active context.
// During reconnection, the old context fires TERMINATED after the new one
// has already been created; quitting in that case would kill the new context.
// Note: context_ is only written from PA callbacks (while the mainloop lock is
// held), so this comparison is safe within any PA callback.
if (backend->context_ == nullptr || backend->context_ == c) {
backend->mainloop_api_->quit(backend->mainloop_api_, 0);
}
break; break;
case PA_CONTEXT_READY: case PA_CONTEXT_READY:
pa_context_get_server_info(c, serverInfoCb, data); pa_context_get_server_info(c, serverInfoCb, data);
@@ -93,6 +104,8 @@ void AudioBackend::contextStateCb(pa_context* c, void* data) {
// So there is no need to lock it again. // So there is no need to lock it again.
if (backend->context_ != nullptr) { if (backend->context_ != nullptr) {
pa_context_disconnect(backend->context_); pa_context_disconnect(backend->context_);
pa_context_unref(backend->context_);
backend->context_ = nullptr;
} }
backend->connectContext(); backend->connectContext();
break; break;