From 45a3a3208a4243d9b0a6500e3dcd0fcfed2dfcea Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 11 Sep 2020 17:42:06 +0300 Subject: 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. Change-Id: I0532f783ae53cc7861e0f08433dc2407aa9c7953 Reviewed-by: David Edmundson (cherry picked from commit 4a4c35a856cf64f0e165cc3cfaeb1a3bbbf471f6) --- src/qtwaylandscanner/qtwaylandscanner.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp index 41e8126e1..1d635f069 100644 --- a/src/qtwaylandscanner/qtwaylandscanner.cpp +++ b/src/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) { -- cgit v1.2.3