From c56c8c8953690bd33019c11f85e0c54093028dae Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 31 Mar 2020 13:52:35 +0200 Subject: [PATCH] WindowServer: Remove applets from AppletManager on client disconnection Disconnecting from WindowServer without explicit calls to DestroyWindow would leave nulled-out WeakPtr's in the AppletManager applet list. This led to a null dereference when adding a new applet, since we were assuming the list contained no nulled-out applets. This patch fixes the issue by always unregistering applet windows from the AppletManager in ~ClientConnection(). We also do an extra pass of pruning any nulled-out WeakPtrs from the applet list when adding to it. Fixes #1551. --- Servers/WindowServer/AppletManager.cpp | 5 +++++ Servers/WindowServer/ClientConnection.cpp | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Servers/WindowServer/AppletManager.cpp b/Servers/WindowServer/AppletManager.cpp index 382222a1d7..16cdf4c9da 100644 --- a/Servers/WindowServer/AppletManager.cpp +++ b/Servers/WindowServer/AppletManager.cpp @@ -71,6 +71,11 @@ void AppletManager::add_applet(Window& applet) { m_applets.append(applet.make_weak_ptr()); + // Prune any dead weak pointers from the applet list. + m_applets.remove_all_matching([](auto& entry) { + return entry.is_null(); + }); + quick_sort(m_applets, [](auto& a, auto& b) { auto index_a = order_vector.find_first_index(a->title()); auto index_b = order_vector.find_first_index(b->title()); diff --git a/Servers/WindowServer/ClientConnection.cpp b/Servers/WindowServer/ClientConnection.cpp index 4b0449d771..a94b9ea4ac 100644 --- a/Servers/WindowServer/ClientConnection.cpp +++ b/Servers/WindowServer/ClientConnection.cpp @@ -81,8 +81,11 @@ ClientConnection::~ClientConnection() { MenuManager::the().close_all_menus_from_client({}, *this); auto windows = move(m_windows); - for (auto& window : windows) + for (auto& window : windows) { window.value->detach_client({}); + if (window.value->type() == WindowType::MenuApplet) + AppletManager::the().remove_applet(window.value); + } } void ClientConnection::die()