wm: fix deadlock in destroy-view handling

The deadlock reported in #3236 could be reproduced via the wm.run script
and the modification of test/nitpicker in commit "nitpicker: fix destroy
with invalid handle" by clicking on the testnit entry of the launchpad.

This patch fixes the deadlock by releasing the locked pointer early in
the destruction path, which is legitimate as the wm is single-threaded.

Fixes #3236
This commit is contained in:
Norman Feske 2021-02-07 13:58:51 +01:00
parent b5fb37ddee
commit 7d568247e3

View File

@ -920,9 +920,21 @@ class Wm::Gui::Session_component : public Rpc_object<Gui::Session>,
void destroy_view(View_handle handle) override
{
try {
Locked_ptr<View> view(_view_handle_registry.lookup(handle));
if (view.valid())
_destroy_view_object(*view);
/*
* Lookup the view but release the lock to prevent the view
* destructor from taking the lock a second time. The locking
* aspect of the weak ptr is not needed within the wm because
* the component is single-threaded.
*/
View *view_ptr = nullptr;
{
Locked_ptr<View> view(_view_handle_registry.lookup(handle));
if (view.valid())
view_ptr = view.operator->();
}
if (view_ptr)
_destroy_view_object(*view_ptr);
_view_handle_registry.free(handle);
} catch (View_handle_registry::Lookup_failed) { }