我正在尝试捕获应用程序崩溃,并向用户显示一个屏幕以确认崩溃报告。这个想法是:当发生崩溃时,我将加载带有崩溃描述和发送按钮的特殊情况的QML。但是我无法重新加载已经存在的main.qml
文件,QApplication::exit()
函数只是不退出主事件循环,因此'crash.qml'屏幕永远不会显示给用户。
这是重现我的问题的最小工作示例:
/// main.cpp
#include <QDebug>
#include <QObject>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <setjmp.h>
#include <signal.h>
#include "cpp.h"
CPP cpp_obj;
sigjmp_buf main_entry;
void signal_handler(int signum) {
signal(SIGSEGV, SIG_DFL); // clear signal handler as we don't need it anymore
qDebug() << "got crash";
qGuiApp->exit(1);
longjmp(main_entry, 1);
}
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QQmlContext* ctext = engine.rootContext();
ctext->setContextProperty("cpp_obj", &cpp_obj);
if (engine.rootObjects().isEmpty())
return -1;
signal(SIGSEGV, signal_handler);
int retcode;
if (setjmp(main_entry) == 0) {
qDebug() << "app starting normal";
retcode=app.exec();
qDebug() << "app returned from normal call, retcode=" << retcode;
} else {
qDebug() << "loading crash qml file";
engine.load(QUrl(QStringLiteral("qrc:/crash.qml")));
qDebug() << "entering crash's main event loop";
retcode=app.exec();
}
qDebug() << "exiting app at the end of the main(), retcode=" << retcode;
return retcode;
}
//cpp.h
#ifndef CPP_H
#define CPP_H
#include <QObject>
class CPP : public QObject
{
Q_OBJECT
public:
explicit CPP(QObject *parent = nullptr);
Q_INVOKABLE void crash_app();
signals:
void app_crashed(QString failure_description);
};
#endif // CPP_H
/// cpp.cpp
#include "cpp.h"
CPP::CPP(QObject *parent) : QObject(parent)
{
}
void CPP::crash_app() {
char *ptr=nullptr;
*ptr='A';
}
///main.qml
import QtQuick 2.11
import QtQuick.Controls 2.4
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
title: qsTr("The App runs fine")
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "Simulate Crash"
onClicked: cpp_obj.crash_app()
}
}
///crash.qml
import QtQuick 2.11
import QtQuick.Controls 2.4
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
title: qsTr("Crash Report")
Label {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "The app has failed"
}
Button {
text: "Submit Crash Report"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
onClicked: {
// TODO: send crash report via UDP
}
}
}
当我运行它时,这就是我在控制台上看到的内容:
QML debugging is enabled. Only use this in a safe environment.
app starting normal
got crash
loading crash qml file
entering crash's main event loop
QCoreApplication::exec: The event loop is already running
exiting app at the end of the main(), retcode= -1
如果还有其他方法可以满足我的需求,我将不胜感激