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:
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user