From 7bf4c434a4d9814b7c8424118d4cd5e47811dd05 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 11 Sep 2020 17:42:06 +0300 Subject: [PATCH] Scanner: Generate code that destroys inert resources In rare cases, the compositor may need to destroy its private data associated with a wl_resource object. For example, one such case may arise when an output has been disconnected and the corresponding QWaylandXdgOutputV1 object needs to be destroyed. Another case is where some resource has become inert. If the QWaylandXdgOutputV1 object has been destroyed and there are still wl_resource objects associated with it, the compositor will crash due to a segfault when somebody calls xdg_output::destroy(). With this change, qtwaylandscanner will generate code that handles destruction of inert resources behind the scenes. Pick-to: 5.15 Change-Id: I0532f783ae53cc7861e0f08433dc2407aa9c7953 Reviewed-by: David Edmundson --- .../qtwaylandscanner/qtwaylandscanner.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/tools/qtwaylandscanner/qtwaylandscanner.cpp b/src/tools/qtwaylandscanner/qtwaylandscanner.cpp index 5b569411931..1a1f8bf16df 100644 --- a/src/tools/qtwaylandscanner/qtwaylandscanner.cpp +++ b/src/tools/qtwaylandscanner/qtwaylandscanner.cpp @@ -719,7 +719,10 @@ bool Scanner::process() printf(" %s::~%s()\n", interfaceName, interfaceName); printf(" {\n"); printf(" for (auto resource : qAsConst(m_resource_map))\n"); - printf(" wl_resource_set_implementation(resource->handle, nullptr, nullptr, nullptr);\n"); + printf(" resource->%s_object = nullptr;\n", interfaceNameStripped); + printf("\n"); + printf(" if (m_resource)\n"); + printf(" m_resource->%s_object = nullptr;\n", interfaceNameStripped); printf("\n"); printf(" if (m_global) {\n"); printf(" wl_global_destroy(m_global);\n"); @@ -808,10 +811,12 @@ bool Scanner::process() printf(" Resource *resource = Resource::fromResource(client_resource);\n"); printf(" Q_ASSERT(resource);\n"); printf(" %s *that = resource->%s_object;\n", interfaceName, interfaceNameStripped); - printf(" that->m_resource_map.remove(resource->client(), resource);\n"); - printf(" that->%s_destroy_resource(resource);\n", interfaceNameStripped); - printf(" if (that->m_resource == resource)\n"); - printf(" that->m_resource = nullptr;\n"); + printf(" if (Q_LIKELY(that)) {\n"); + printf(" that->m_resource_map.remove(resource->client(), resource);\n"); + printf(" that->%s_destroy_resource(resource);\n", interfaceNameStripped); + printf(" if (that->m_resource == resource)\n"); + printf(" that->m_resource = nullptr;\n"); + printf(" }\n"); printf(" delete resource;\n"); printf(" }\n"); printf("\n"); @@ -885,6 +890,11 @@ bool Scanner::process() printf(" {\n"); printf(" Q_UNUSED(client);\n"); printf(" Resource *r = Resource::fromResource(resource);\n"); + printf(" if (Q_UNLIKELY(!r->%s_object)) {\n", interfaceNameStripped); + if (e.type == "destructor") + printf(" wl_resource_destroy(resource);\n"); + printf(" return;\n"); + printf(" }\n"); printf(" static_cast<%s *>(r->%s_object)->%s_%s(\n", interfaceName, interfaceNameStripped, interfaceNameStripped, e.name.constData()); printf(" r"); for (const WaylandArgument &a : e.arguments) {