Compare commits

...

5 commits

Author SHA1 Message Date
Mia Herkt
ee1100eb98
wayland/buffer: drop unused GLESv3 include
That one is often in a separate Mesa package and contrary to GLESv2
doesn’t come with a pkg-config file. Mildly annoying…
2026-03-29 09:31:28 +02:00
outfoxxed
9bf752ac33
crash: add std::terminate handler 2026-03-28 23:07:37 -07:00
outfoxxed
313f4e47f6
core: track XDG_CURRENT_DESKTOP in debuginfo 2026-03-28 20:28:03 -07:00
outfoxxed
6ef86dd5aa
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.
2026-03-28 20:27:57 -07:00
outfoxxed
308f1e249b
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.
2026-03-28 20:27:48 -07:00
7 changed files with 52 additions and 9 deletions

View file

@ -129,12 +129,13 @@ QString envInfo() {
auto stream = QTextStream(&info);
for (auto** envp = environ; *envp != nullptr; ++envp) { // NOLINT
auto prefixes = std::array<std::string_view, 5> {
auto prefixes = std::array<std::string_view, 6> {
"QS_",
"QT_",
"QML_",
"QML2_",
"QSG_",
"XDG_CURRENT_DESKTOP=",
};
for (const auto& prefix: prefixes) {

View file

@ -9,6 +9,18 @@ static QVector<QsEnginePlugin*> 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();
}

View file

@ -18,12 +18,14 @@ public:
virtual QString name() { return QString(); }
virtual QList<QString> 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();

View file

@ -5,9 +5,11 @@
#include <csignal>
#include <cstdio>
#include <cstring>
#include <exception>
#include <cpptrace/basic.hpp>
#include <cpptrace/forward.hpp>
#include <cpptrace/utils.hpp>
#include <qdatastream.h>
#include <qfile.h>
#include <qlogging.h>
@ -58,6 +60,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<cpptrace::frame_ptr, 1024>();
auto frameCount = cpptrace::safe_generate_raw_trace(traceBuffer.data(), traceBuffer.size(), 1);
@ -79,13 +87,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 +135,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<char, 48>();
auto logFdStr = std::array<char, 48>();
@ -155,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() {
@ -203,6 +221,8 @@ void CrashHandler::init() {
// NOLINTEND (misc-include-cleaner)
std::set_terminate(&handleCppTerminate);
qCInfo(logCrashHandler) << "Crash handler initialized.";
}

View file

@ -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);

View file

@ -10,7 +10,6 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GL/gl.h>
#include <GLES3/gl32.h>
#include <fcntl.h>
#include <gbm.h>
#include <libdrm/drm_fourcc.h>

View file

@ -33,8 +33,9 @@ class WaylandPlugin: public QsEnginePlugin {
return isWayland;
}
void preinit() override { installWlProxySafeDeref(); }
void init() override {
installWlProxySafeDeref();
installPlatformMenuHook();
installPopupPositioner();
}