From 38cc11c3b083c473e421ac9a6ead16e77f3469eb Mon Sep 17 00:00:00 2001 From: Shivank Garg Date: Thu, 13 Aug 2026 00:50:42 +0530 Subject: [PATCH] privacy: disconnect pending timeouts on destruction The privacy module registers timeout callbacks in the GLib main context. The GeoClue callback uses sigc::mem_fun() with the Privacy object, but the connection remains active when the module is destroyed during a bar reload. If the timeout runs after destruction, it dereferences the freed Privacy object and crashes Waybar: #0 waybar::modules::privacy::Privacy::locationTimeout(bool) #4 g_main_context_iteration() #5 g_application_run() Disconnect the GeoClue and visibility timeout connections in the Privacy destructor so no callback can run after the module is gone. The unpatched binary crashed after four SIGUSR2 reloads at 1.5-second intervals. The patched binary survived ten reloads. Fixes: eeb7bc702e8e ("Added GeoClue2 privacy item") Assisted-by: Claude Opus + Cursor --- include/modules/privacy/privacy.hpp | 1 + src/modules/privacy/privacy.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/modules/privacy/privacy.hpp b/include/modules/privacy/privacy.hpp index 7307afc9..41145e50 100644 --- a/include/modules/privacy/privacy.hpp +++ b/include/modules/privacy/privacy.hpp @@ -17,6 +17,7 @@ namespace waybar::modules::privacy { class Privacy : public AModule { public: Privacy(const std::string&, const Json::Value&, Gtk::Orientation, const std::string& pos); + ~Privacy() override; auto update() -> void override; private: diff --git a/src/modules/privacy/privacy.cpp b/src/modules/privacy/privacy.cpp index 7bb9de92..76762cf5 100644 --- a/src/modules/privacy/privacy.cpp +++ b/src/modules/privacy/privacy.cpp @@ -119,6 +119,15 @@ Privacy::Privacy(const std::string& id, const Json::Value& config, Gtk::Orientat sigc::mem_fun(*this, &Privacy::onGeoCluePrivacyNodesChanged)); } +Privacy::~Privacy() { + // Both timeouts are attached to the global main context, which outlives this + // module when the bar is reloaded. sigc::connection's destructor does not + // disconnect, and the members are torn down after the backends they use, so a + // pending timeout would dispatch onto freed memory. + geoclue_timeout_conn.disconnect(); + visibility_conn.disconnect(); +} + void Privacy::onPWPrivacyNodesChanged() { mutex_.lock(); nodes_audio_out.clear();