CrashHandler: Display signal causing the crash.

Change-Id: Ib6bb04b8e70bbe99e6517536a62c80a920a2ea01
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Nikolai Kosjar
2012-10-22 13:45:10 +02:00
committed by hjk
parent 60ffb91ffd
commit 4a91102306
6 changed files with 30 additions and 21 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
} }

View File

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