From 308f1e249b178c394509341ba7ab49fc98b9c824 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 28 Mar 2026 20:14:58 -0700 Subject: [PATCH 1/5] crash: unmask signals before reexec Signals were previously left masked before reexec, causing UB if a child were to crash again, instead of triggering the reporter. This might've been responsible for a number of unexplainable bugs. --- src/crash/handler.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/crash/handler.cpp b/src/crash/handler.cpp index 8f37085..045a148 100644 --- a/src/crash/handler.cpp +++ b/src/crash/handler.cpp @@ -58,6 +58,12 @@ void signalHandler( siginfo_t* /*info*/, // NOLINT (misc-include-cleaner) void* /*context*/ ) { + // NOLINTBEGIN (misc-include-cleaner) + sigset_t set; + sigfillset(&set); + sigprocmask(SIG_UNBLOCK, &set, nullptr); + // NOLINTEND + if (CrashInfo::INSTANCE.traceFd != -1) { auto traceBuffer = std::array(); auto frameCount = cpptrace::safe_generate_raw_trace(traceBuffer.data(), traceBuffer.size(), 1); @@ -79,13 +85,9 @@ void signalHandler( fail:; } + // TODO: coredump fork and crash reporter remain as zombies, fix auto coredumpPid = fork(); if (coredumpPid == 0) { - // NOLINTBEGIN (misc-include-cleaner) - sigset_t set; - sigfillset(&set); - sigprocmask(SIG_UNBLOCK, &set, nullptr); - // NOLINTEND raise(sig); _exit(-1); } @@ -131,7 +133,6 @@ void signalHandler( perror("Failed to fork and launch crash reporter.\n"); _exit(-1); } else if (pid == 0) { - // dup to remove CLOEXEC auto dumpFdStr = std::array(); auto logFdStr = std::array(); From 6ef86dd5aa3dec6fe7dbc8f51e08ad6d1b5c8cc0 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 28 Mar 2026 20:17:07 -0700 Subject: [PATCH 2/5] crash: run platform compat hooks in crash reporter init For some reason, QtWayland crashes we work around trigger in this path. This was previously masked when the crash reporter didn't unmask signals, as long as the original process crashed with SIGSEGV. --- src/core/plugin.cpp | 16 ++++++++++++++++ src/core/plugin.hpp | 2 ++ src/crash/main.cpp | 4 ++++ src/wayland/init.cpp | 3 ++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/core/plugin.cpp b/src/core/plugin.cpp index 0eb9a06..e6cd1bb 100644 --- a/src/core/plugin.cpp +++ b/src/core/plugin.cpp @@ -9,6 +9,18 @@ static QVector plugins; // NOLINT void QsEnginePlugin::registerPlugin(QsEnginePlugin& plugin) { plugins.push_back(&plugin); } +void QsEnginePlugin::preinitPluginsOnly() { + plugins.removeIf([](QsEnginePlugin* plugin) { return !plugin->applies(); }); + + std::ranges::sort(plugins, [](QsEnginePlugin* a, QsEnginePlugin* b) { + return b->dependencies().contains(a->name()); + }); + + for (QsEnginePlugin* plugin: plugins) { + plugin->preinit(); + } +} + void QsEnginePlugin::initPlugins() { plugins.removeIf([](QsEnginePlugin* plugin) { return !plugin->applies(); }); @@ -16,6 +28,10 @@ void QsEnginePlugin::initPlugins() { return b->dependencies().contains(a->name()); }); + for (QsEnginePlugin* plugin: plugins) { + plugin->preinit(); + } + for (QsEnginePlugin* plugin: plugins) { plugin->init(); } diff --git a/src/core/plugin.hpp b/src/core/plugin.hpp index f0c14dc..f692e91 100644 --- a/src/core/plugin.hpp +++ b/src/core/plugin.hpp @@ -18,12 +18,14 @@ public: virtual QString name() { return QString(); } virtual QList dependencies() { return {}; } virtual bool applies() { return true; } + virtual void preinit() {} virtual void init() {} virtual void registerTypes() {} virtual void constructGeneration(EngineGeneration& /*unused*/) {} // NOLINT virtual void onReload() {} static void registerPlugin(QsEnginePlugin& plugin); + static void preinitPluginsOnly(); static void initPlugins(); static void runConstructGeneration(EngineGeneration& generation); static void runOnReload(); diff --git a/src/crash/main.cpp b/src/crash/main.cpp index 30cf94d..6533b43 100644 --- a/src/crash/main.cpp +++ b/src/crash/main.cpp @@ -25,6 +25,7 @@ #include "../core/logging.hpp" #include "../core/logging_p.hpp" #include "../core/paths.hpp" +#include "../core/plugin.hpp" #include "../core/ringbuf.hpp" #include "interface.hpp" @@ -238,6 +239,9 @@ void qsCheckCrash(int argc, char** argv) { qCInfo(logCrashReporter) << "Starting crash reporter..."; + // Required platform compatibility hooks + QsEnginePlugin::preinitPluginsOnly(); + recordCrashInfo(crashDir, info.instance); auto gui = CrashReporterGui(crashDir.path(), crashProc); diff --git a/src/wayland/init.cpp b/src/wayland/init.cpp index 790cebb..579e42a 100644 --- a/src/wayland/init.cpp +++ b/src/wayland/init.cpp @@ -33,8 +33,9 @@ class WaylandPlugin: public QsEnginePlugin { return isWayland; } + void preinit() override { installWlProxySafeDeref(); } + void init() override { - installWlProxySafeDeref(); installPlatformMenuHook(); installPopupPositioner(); } From 313f4e47f6f3d7204586721b2fbd0a54d542a84c Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 28 Mar 2026 20:25:58 -0700 Subject: [PATCH 3/5] core: track XDG_CURRENT_DESKTOP in debuginfo --- src/core/debuginfo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/debuginfo.cpp b/src/core/debuginfo.cpp index ae227f8..abc467d 100644 --- a/src/core/debuginfo.cpp +++ b/src/core/debuginfo.cpp @@ -129,12 +129,13 @@ QString envInfo() { auto stream = QTextStream(&info); for (auto** envp = environ; *envp != nullptr; ++envp) { // NOLINT - auto prefixes = std::array { + auto prefixes = std::array { "QS_", "QT_", "QML_", "QML2_", "QSG_", + "XDG_CURRENT_DESKTOP=", }; for (const auto& prefix: prefixes) { From 9bf752ac33b2181356d33251c3b1b4dedde0bbc6 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 28 Mar 2026 23:07:37 -0700 Subject: [PATCH 4/5] crash: add std::terminate handler --- src/crash/handler.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/crash/handler.cpp b/src/crash/handler.cpp index 045a148..33506a6 100644 --- a/src/crash/handler.cpp +++ b/src/crash/handler.cpp @@ -5,9 +5,11 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -156,6 +158,21 @@ void signalHandler( } } +void handleCppTerminate() { + if (auto ptr = std::current_exception()) { + try { + std::rethrow_exception(ptr); + } catch (std::exception& e) { + qFatal().nospace() << "Terminate called with C++ exception (" + << cpptrace::demangle(typeid(e).name()).data() << "): " << e.what(); + } catch (...) { + qFatal() << "Terminate called with non exception object"; + } + } + + qFatal() << "Terminate called without active C++ exception"; +} + } // namespace void CrashHandler::init() { @@ -204,6 +221,8 @@ void CrashHandler::init() { // NOLINTEND (misc-include-cleaner) + std::set_terminate(&handleCppTerminate); + qCInfo(logCrashHandler) << "Crash handler initialized."; } From ee1100eb98d5033d8d4b76bf9fb0e720fec4c191 Mon Sep 17 00:00:00 2001 From: Mia Herkt Date: Sun, 29 Mar 2026 09:31:28 +0200 Subject: [PATCH 5/5] wayland/buffer: drop unused GLESv3 include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That one is often in a separate Mesa package and contrary to GLESv2 doesn’t come with a pkg-config file. Mildly annoying… --- src/wayland/buffer/dmabuf.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wayland/buffer/dmabuf.cpp b/src/wayland/buffer/dmabuf.cpp index ed9dbeb..47462fb 100644 --- a/src/wayland/buffer/dmabuf.cpp +++ b/src/wayland/buffer/dmabuf.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include