Merge pull request #5115 from jaschiu/jaschiu-patch-1

fix(tray): segfault due to use-after-free from iterating children
This commit is contained in:
Alexis Rouillard
2026-07-04 01:42:36 +02:00
committed by GitHub
2 changed files with 8 additions and 3 deletions
+1
View File
@@ -28,6 +28,7 @@ class Tray : public AModule {
SNI::Watcher::singleton watcher_; SNI::Watcher::singleton watcher_;
std::vector<std::string> ignore_list_; std::vector<std::string> ignore_list_;
SNI::Host host_; SNI::Host host_;
std::vector<Item*> items_;
}; };
} // namespace waybar::modules::SNI } // namespace waybar::modules::SNI
+7 -3
View File
@@ -68,6 +68,7 @@ void Tray::onAdd(std::unique_ptr<Item>& item) {
} else { } else {
box_.pack_start(item->event_box); box_.pack_start(item->event_box);
} }
items_.push_back(item.get());
spdlog::debug("Tray::onAdd deferred check - checking ignore list"); spdlog::debug("Tray::onAdd deferred check - checking ignore list");
host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1)); host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1));
@@ -79,6 +80,7 @@ void Tray::onAdd(std::unique_ptr<Item>& item) {
void Tray::onRemove(std::unique_ptr<Item>& item) { void Tray::onRemove(std::unique_ptr<Item>& item) {
box_.remove(item->event_box); box_.remove(item->event_box);
items_.erase(std::remove(items_.begin(), items_.end(), item.get()), items_.end());
dp.emit(); dp.emit();
} }
@@ -89,9 +91,11 @@ auto Tray::update() -> void {
host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1)); host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1));
} }
std::vector<Gtk::Widget*> children = box_.get_children(); // Show tray only when items are visible. Iterate the managed items_ list
event_box_.set_visible(std::any_of(children.begin(), children.end(), // instead of box_.get_children() to avoid a use-after-free on raw widget
[](Gtk::Widget* child) { return child->get_visible(); })); // pointers that may dangle after items are destroyed asynchronously.
event_box_.set_visible(std::any_of(items_.begin(), items_.end(),
[](Item* item) { return item->event_box.get_visible(); }));
AModule::update(); AModule::update();
} }