fix(sway/window): resolve app icon on the main thread to stop icon-theme race
onCmd() runs on the sway IPC worker thread and called updateAppIconName(), which touches the global Gtk::IconTheme cache. Concurrent access with the main thread's draw (propagate_draw -> gtk_icon_theme_has_icon -> g_hash_table_lookup) races and can segfault, notably on multi-monitor and focus changes. Move the icon-theme lookup into Window::update(), which runs on the main thread via dp.emit(), and only store app_id_/app_class_ in onCmd(). Fixes #4108.
This commit is contained in:
@@ -43,7 +43,9 @@ void Window::onCmd(const struct Ipc::ipc_response& res) {
|
||||
auto output = payload["output"].isString() ? payload["output"].asString() : "";
|
||||
std::tie(app_nb_, floating_count_, windowId_, window_, app_id_, app_class_, shell_, layout_,
|
||||
marks_) = getFocusedNode(payload["nodes"], output);
|
||||
updateAppIconName(app_id_, app_class_);
|
||||
// Do not resolve the app icon here: onCmd runs on the sway IPC worker thread and
|
||||
// updateAppIconName() touches the global Gtk::IconTheme cache, which is not thread-safe.
|
||||
// The icon is resolved in update() on the main thread instead (triggered by dp.emit()).
|
||||
dp.emit();
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("Window: {}", e.what());
|
||||
@@ -102,6 +104,9 @@ auto Window::update() -> void {
|
||||
setTooltipMarkup(window_);
|
||||
}
|
||||
|
||||
// Resolve the app icon on the main thread to avoid racing with GTK draw on the
|
||||
// global Gtk::IconTheme cache (see onCmd).
|
||||
updateAppIconName(app_id_, app_class_);
|
||||
updateAppIcon();
|
||||
|
||||
// Call parent update
|
||||
|
||||
Reference in New Issue
Block a user