Skip to content

Commit 445e2ae

Browse files
committed
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
1 parent 9d8a835 commit 445e2ae

2 files changed

Lines changed: 12 additions & 3 deletions

File tree

include/bar.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ class Bar : public sigc::trackable {
131131

132132
waybar::util::KillSignalAction onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1;
133133
waybar::util::KillSignalAction onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2;
134+
135+
/* Disconnected in ~Bar before the modules are destroyed (#5182). */
136+
sigc::connection map_conn_;
137+
sigc::connection unmap_conn_;
134138
};
135139

136140
} // namespace waybar

src/bar.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,12 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
269269

270270
window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap));
271271

272-
window.signal_unmap().connect([this]() {
272+
unmap_conn_ = window.signal_unmap().connect([this]() {
273273
spdlog::debug("Output {} unmapped (DPMS off), suspending modules", output->name);
274274
toggleSuspend(true);
275275
});
276276

277-
window.signal_map().connect([this]() {
277+
map_conn_ = window.signal_map().connect([this]() {
278278
spdlog::debug("Output {} mapped (DPMS on), resuming modules", output->name);
279279
toggleSuspend(false);
280280
});
@@ -352,7 +352,12 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
352352
}
353353

354354
/* Need to define it here because of forward declared members */
355-
waybar::Bar::~Bar() = default;
355+
waybar::Bar::~Bar() {
356+
/* Destroying the window emits `unmap`, whose handler runs toggleSuspend() over
357+
* modules_all_ -- already freed by this point. Disconnect first (#5182). */
358+
unmap_conn_.disconnect();
359+
map_conn_.disconnect();
360+
}
356361

357362
void waybar::Bar::setMode(const std::string& mode) {
358363
using namespace std::literals::string_literals;

0 commit comments

Comments
 (0)