forked from qt-creator/qt-creator
CrashHandler: Display signal causing the crash.
Change-Id: Ib6bb04b8e70bbe99e6517536a62c80a920a2ea01 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -88,10 +88,10 @@ public:
|
|||||||
class CrashHandlerPrivate
|
class CrashHandlerPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CrashHandlerPrivate(pid_t pid, CrashHandler *crashHandler)
|
CrashHandlerPrivate(pid_t pid, const QString &signalName, CrashHandler *crashHandler)
|
||||||
: pid(pid),
|
: pid(pid),
|
||||||
creatorInPath(Utils::Environment::systemEnvironment().searchInPath(QtCreatorExecutable)),
|
creatorInPath(Utils::Environment::systemEnvironment().searchInPath(QtCreatorExecutable)),
|
||||||
dialog(crashHandler) {}
|
dialog(crashHandler, signalName) {}
|
||||||
|
|
||||||
const pid_t pid;
|
const pid_t pid;
|
||||||
const QString creatorInPath; // Backup debugger.
|
const QString creatorInPath; // Backup debugger.
|
||||||
@@ -103,8 +103,8 @@ public:
|
|||||||
QStringList restartAppEnvironment;
|
QStringList restartAppEnvironment;
|
||||||
};
|
};
|
||||||
|
|
||||||
CrashHandler::CrashHandler(pid_t pid, QObject *parent)
|
CrashHandler::CrashHandler(pid_t pid, const QString &signalName, QObject *parent)
|
||||||
: QObject(parent), d(new CrashHandlerPrivate(pid, this))
|
: QObject(parent), d(new CrashHandlerPrivate(pid, signalName, this))
|
||||||
{
|
{
|
||||||
connect(&d->backtraceCollector, SIGNAL(error(QString)), SLOT(onError(QString)));
|
connect(&d->backtraceCollector, SIGNAL(error(QString)), SLOT(onError(QString)));
|
||||||
connect(&d->backtraceCollector, SIGNAL(backtraceChunk(QString)), SLOT(onBacktraceChunk(QString)));
|
connect(&d->backtraceCollector, SIGNAL(backtraceChunk(QString)), SLOT(onBacktraceChunk(QString)));
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class CrashHandler : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit CrashHandler(pid_t pid, QObject *parent = 0);
|
explicit CrashHandler(pid_t pid, const QString &signalName, QObject *parent = 0);
|
||||||
~CrashHandler();
|
~CrashHandler();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ static const char SettingsApplication[] = "QtCreator";
|
|||||||
static const char SettingsKeySkipWarningAbortingBacktrace[]
|
static const char SettingsKeySkipWarningAbortingBacktrace[]
|
||||||
= "CrashHandler/SkipWarningAbortingBacktrace";
|
= "CrashHandler/SkipWarningAbortingBacktrace";
|
||||||
|
|
||||||
CrashHandlerDialog::CrashHandlerDialog(CrashHandler *handler, QWidget *parent) :
|
CrashHandlerDialog::CrashHandlerDialog(CrashHandler *handler, const QString &signalName,
|
||||||
|
QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
m_crashHandler(handler),
|
m_crashHandler(handler),
|
||||||
m_ui(new Ui::CrashHandlerDialog)
|
m_ui(new Ui::CrashHandlerDialog)
|
||||||
@@ -67,7 +68,7 @@ CrashHandlerDialog::CrashHandlerDialog(CrashHandler *handler, QWidget *parent) :
|
|||||||
connect(m_ui->debugAppButton, SIGNAL(clicked()), m_crashHandler, SLOT(debugApplication()));
|
connect(m_ui->debugAppButton, SIGNAL(clicked()), m_crashHandler, SLOT(debugApplication()));
|
||||||
connect(m_ui->closeButton, SIGNAL(clicked()), this, SLOT(close()));
|
connect(m_ui->closeButton, SIGNAL(clicked()), this, SLOT(close()));
|
||||||
|
|
||||||
setApplicationInfo();
|
setApplicationInfo(signalName);
|
||||||
}
|
}
|
||||||
|
|
||||||
CrashHandlerDialog::~CrashHandlerDialog()
|
CrashHandlerDialog::~CrashHandlerDialog()
|
||||||
@@ -120,14 +121,16 @@ void CrashHandlerDialog::disableDebugAppButton()
|
|||||||
m_ui->debugAppButton->setDisabled(true);
|
m_ui->debugAppButton->setDisabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashHandlerDialog::setApplicationInfo()
|
void CrashHandlerDialog::setApplicationInfo(const QString &signalName)
|
||||||
{
|
{
|
||||||
const QString ideName = QLatin1String("Qt Creator");
|
const QString ideName = QLatin1String("Qt Creator");
|
||||||
const QString contents = tr(
|
const QString title = tr("%1 has closed unexpectedly (Signal \"%2\")").arg(ideName, signalName);
|
||||||
"<p><b>%1 has closed unexpectedly.</b></p>"
|
const QString introLabelContents = tr(
|
||||||
|
"<p><b>%1.</b></p>"
|
||||||
"<p>Please file a <a href='%2'>bug report</a> with the debug information provided below.</p>")
|
"<p>Please file a <a href='%2'>bug report</a> with the debug information provided below.</p>")
|
||||||
.arg(ideName, QLatin1String(URL_BUGTRACKER));
|
.arg(title, QLatin1String(URL_BUGTRACKER));
|
||||||
m_ui->introLabel->setText(contents);
|
m_ui->introLabel->setText(introLabelContents);
|
||||||
|
setWindowTitle(title);
|
||||||
|
|
||||||
QString revision;
|
QString revision;
|
||||||
#ifdef IDE_REVISION
|
#ifdef IDE_REVISION
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QString;
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class CrashHandlerDialog;
|
class CrashHandlerDialog;
|
||||||
}
|
}
|
||||||
@@ -45,11 +46,12 @@ class CrashHandlerDialog : public QDialog
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CrashHandlerDialog(CrashHandler *handler, QWidget *parent = 0);
|
explicit CrashHandlerDialog(CrashHandler *handler, const QString &signalName,
|
||||||
|
QWidget *parent = 0);
|
||||||
~CrashHandlerDialog();
|
~CrashHandlerDialog();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setApplicationInfo();
|
void setApplicationInfo(const QString &signalName);
|
||||||
void appendDebugInfo(const QString &chunk);
|
void appendDebugInfo(const QString &chunk);
|
||||||
void selectLineWithContents(const QString &text);
|
void selectLineWithContents(const QString &text);
|
||||||
void setToFinalState();
|
void setToFinalState();
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
static const char *crashHandlerPathC;
|
static const char *crashHandlerPathC;
|
||||||
static void *signalHandlerStack;
|
static void *signalHandlerStack;
|
||||||
|
|
||||||
extern "C" void signalHandler(int /*signal*/)
|
extern "C" void signalHandler(int signal)
|
||||||
{
|
{
|
||||||
#ifdef Q_WS_X11
|
#ifdef Q_WS_X11
|
||||||
// Kill window since it's frozen anyway.
|
// Kill window since it's frozen anyway.
|
||||||
@@ -70,7 +70,7 @@ extern "C" void signalHandler(int /*signal*/)
|
|||||||
case -1: // error
|
case -1: // error
|
||||||
break;
|
break;
|
||||||
case 0: // child
|
case 0: // child
|
||||||
execl(crashHandlerPathC, crashHandlerPathC, (char *) 0);
|
execl(crashHandlerPathC, crashHandlerPathC, strsignal(signal), (char *) 0);
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
default: // parent
|
default: // parent
|
||||||
waitpid(pid, 0, 0);
|
waitpid(pid, 0, 0);
|
||||||
@@ -117,8 +117,10 @@ void setupCrashHandler()
|
|||||||
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_ONSTACK;
|
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_ONSTACK;
|
||||||
const int signalsToHandle[] = { SIGILL, SIGFPE, SIGSEGV, SIGBUS, 0 };
|
const int signalsToHandle[] = { SIGILL, SIGFPE, SIGSEGV, SIGBUS, 0 };
|
||||||
for (int i = 0; signalsToHandle[i]; ++i) {
|
for (int i = 0; signalsToHandle[i]; ++i) {
|
||||||
if (sigaction(signalsToHandle[i], &sa, 0) == -1 )
|
if (sigaction(signalsToHandle[i], &sa, 0) == -1 ) {
|
||||||
qWarning("Warning: Failed to install signal handler for SIGILL (%s).", Q_FUNC_INFO);
|
qWarning("Warning: Failed to install signal handler for signal \"%s\" (%s).",
|
||||||
|
strsignal(signalsToHandle[i]), Q_FUNC_INFO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // BUILD_CRASH_HANDLER
|
#endif // BUILD_CRASH_HANDLER
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// Called by signal handler of qtcreator.
|
||||||
|
// Usage: $0 <name of signal causing the crash>
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
@@ -51,15 +53,15 @@ int main(int argc, char *argv[])
|
|||||||
Q_PID parentPid = getppid();
|
Q_PID parentPid = getppid();
|
||||||
QString parentExecutable = QFile::symLinkTarget(QString::fromLatin1("/proc/%1/exe")
|
QString parentExecutable = QFile::symLinkTarget(QString::fromLatin1("/proc/%1/exe")
|
||||||
.arg(QString::number(parentPid)));
|
.arg(QString::number(parentPid)));
|
||||||
if (argc > 1 || !parentExecutable.contains("qtcreator")) {
|
if (argc > 2 || !parentExecutable.contains("qtcreator")) {
|
||||||
QTextStream err(stderr);
|
QTextStream err(stderr);
|
||||||
err << QString::fromLatin1("This crash handler will be called by Qt Creator itself. "
|
err << QString::fromLatin1("This crash handler will be called by Qt Creator itself. "
|
||||||
"Don't call this manually.\n");
|
"Do not call this manually.\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run.
|
// Run.
|
||||||
CrashHandler *crashHandler = new CrashHandler(parentPid);
|
CrashHandler *crashHandler = new CrashHandler(parentPid, app.arguments().at(1));
|
||||||
crashHandler->run();
|
crashHandler->run();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|||||||
Reference in New Issue
Block a user