fix(bar): avoid use-after-free segfault on exit

Members are destroyed in reverse declaration order, so modules_all_ (and
the modules it owns) are gone before the GtkWindow. Tearing down a mapped
window emits `unmap`, whose handler runs toggleSuspend() over the already
freed modules. Disconnect the map/unmap handlers in ~Bar first.

Fixes #5182
This commit is contained in:
Alex
2026-07-05 22:03:28 +02:00
parent 9d8a8356b5
commit 445e2aec1f
2 changed files with 12 additions and 3 deletions
+4
View File
@@ -131,6 +131,10 @@ class Bar : public sigc::trackable {
waybar::util::KillSignalAction onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1;
waybar::util::KillSignalAction onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2;
/* Disconnected in ~Bar before the modules are destroyed (#5182). */
sigc::connection map_conn_;
sigc::connection unmap_conn_;
};
} // namespace waybar
+8 -3
View File
@@ -269,12 +269,12 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap));
window.signal_unmap().connect([this]() {
unmap_conn_ = window.signal_unmap().connect([this]() {
spdlog::debug("Output {} unmapped (DPMS off), suspending modules", output->name);
toggleSuspend(true);
});
window.signal_map().connect([this]() {
map_conn_ = window.signal_map().connect([this]() {
spdlog::debug("Output {} mapped (DPMS on), resuming modules", output->name);
toggleSuspend(false);
});
@@ -352,7 +352,12 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
}
/* Need to define it here because of forward declared members */
waybar::Bar::~Bar() = default;
waybar::Bar::~Bar() {
/* Destroying the window emits `unmap`, whose handler runs toggleSuspend() over
* modules_all_ -- already freed by this point. Disconnect first (#5182). */
unmap_conn_.disconnect();
map_conn_.disconnect();
}
void waybar::Bar::setMode(const std::string& mode) {
using namespace std::literals::string_literals;