summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/QtcTool.qbs3
-rw-r--r--src/tools/qml2puppet/qml2puppet.pro9
-rw-r--r--src/tools/qml2puppet/qml2puppet/qml2puppet.pro10
-rw-r--r--src/tools/qtcdebugger/qtcdebugger.qbs2
-rw-r--r--src/tools/qtcreatorcrashhandler/backtracecollector.cpp128
-rw-r--r--src/tools/qtcreatorcrashhandler/backtracecollector.h64
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandler.cpp313
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandler.h69
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp180
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandlerdialog.h71
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandlerdialog.ui147
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandlersetup.cpp134
-rw-r--r--src/tools/qtcreatorcrashhandler/crashhandlersetup.h36
-rw-r--r--src/tools/qtcreatorcrashhandler/main.cpp68
-rw-r--r--src/tools/qtcreatorcrashhandler/qtcreatorcrashhandler.pro31
-rw-r--r--src/tools/qtcreatorcrashhandler/qtcreatorcrashhandler.qbs33
-rw-r--r--src/tools/qtcreatorcrashhandler/utils.cpp43
-rw-r--r--src/tools/qtcreatorcrashhandler/utils.h41
-rw-r--r--src/tools/sdktool/sdktool.qbs14
-rw-r--r--src/tools/tools.pro9
20 files changed, 1395 insertions, 10 deletions
diff --git a/src/tools/QtcTool.qbs b/src/tools/QtcTool.qbs
index 7669496dca..a8b4f4d522 100644
--- a/src/tools/QtcTool.qbs
+++ b/src/tools/QtcTool.qbs
@@ -1,8 +1,9 @@
import qbs.base 1.0
+import "../../qbs/defaults.js" as Defaults
Application {
Depends { name: "cpp" }
- cpp.defines: project.additionalCppDefines
+ cpp.defines: Defaults.defines(qbs)
cpp.linkerFlags: {
if (qbs.buildVariant == "release" && (qbs.toolchain == "gcc" || qbs.toolchain == "mingw"))
return ["-Wl,-s"]
diff --git a/src/tools/qml2puppet/qml2puppet.pro b/src/tools/qml2puppet/qml2puppet.pro
new file mode 100644
index 0000000000..b8e17814be
--- /dev/null
+++ b/src/tools/qml2puppet/qml2puppet.pro
@@ -0,0 +1,9 @@
+TEMPLATE = subdirs
+
+include(../../../qtcreator.pri)
+
+greaterThan(QT_MAJOR_VERSION, 4) {
+ QT += declarative-private core-private
+ SUBDIRS += qml2puppet
+}
+
diff --git a/src/tools/qml2puppet/qml2puppet/qml2puppet.pro b/src/tools/qml2puppet/qml2puppet/qml2puppet.pro
new file mode 100644
index 0000000000..f791416d76
--- /dev/null
+++ b/src/tools/qml2puppet/qml2puppet/qml2puppet.pro
@@ -0,0 +1,10 @@
+TARGET = qml2puppet
+
+TEMPLATE = app
+
+include(../../../../qtcreator.pri)
+
+DESTDIR = $$IDE_BIN_PATH
+include(../../../rpath.pri)
+
+include(../../../../share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri)
diff --git a/src/tools/qtcdebugger/qtcdebugger.qbs b/src/tools/qtcdebugger/qtcdebugger.qbs
index bc416fb95b..5b86287746 100644
--- a/src/tools/qtcdebugger/qtcdebugger.qbs
+++ b/src/tools/qtcdebugger/qtcdebugger.qbs
@@ -21,6 +21,6 @@ QtcTool {
files: [
"main.cpp",
"../../shared/registryaccess/registryaccess.cpp",
- "../../shared/registryaccess/registryaccess.h"
+ "../../shared/registryaccess/registryaccess.h",
]
}
diff --git a/src/tools/qtcreatorcrashhandler/backtracecollector.cpp b/src/tools/qtcreatorcrashhandler/backtracecollector.cpp
new file mode 100644
index 0000000000..e62e2432c1
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/backtracecollector.cpp
@@ -0,0 +1,128 @@
+/**************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "backtracecollector.h"
+
+#include <QDebug>
+#include <QScopedPointer>
+#include <QTemporaryFile>
+
+const char GdbBatchCommands[] =
+ "set height 0\n"
+ "set width 0\n"
+ "thread\n"
+ "thread apply all backtrace full\n";
+
+class BacktraceCollectorPrivate
+{
+public:
+ BacktraceCollectorPrivate() : errorOccurred(false) {}
+
+ bool errorOccurred;
+ QScopedPointer<QTemporaryFile> commandFile;
+ QProcess debugger;
+ QString output;
+};
+
+BacktraceCollector::BacktraceCollector(QObject *parent) :
+ QObject(parent), d(new BacktraceCollectorPrivate)
+{
+ connect(&d->debugger, SIGNAL(finished(int,QProcess::ExitStatus)),
+ SLOT(onDebuggerFinished(int,QProcess::ExitStatus)));
+ connect(&d->debugger, SIGNAL(error(QProcess::ProcessError)),
+ SLOT(onDebuggerError(QProcess::ProcessError)));
+ connect(&d->debugger, SIGNAL(readyRead()), SLOT(onDebuggerOutputAvailable()));
+ d->debugger.setProcessChannelMode(QProcess::MergedChannels);
+}
+
+BacktraceCollector::~BacktraceCollector()
+{
+ delete d;
+}
+
+void BacktraceCollector::run(Q_PID pid)
+{
+ d->debugger.start(QLatin1String("gdb"), QStringList()
+ << QLatin1String("--nw") // Do not use a window interface.
+ << QLatin1String("--nx") // Do not read .gdbinit file.
+ << QLatin1String("--batch") // Exit after processing options.
+ << QLatin1String("--command") << createTemporaryCommandFile()
+ << QLatin1String("--pid") << QString::number(pid)
+ );
+}
+
+bool BacktraceCollector::isRunning() const
+{
+ return d->debugger.state() == QProcess::Running;
+}
+
+void BacktraceCollector::kill()
+{
+ d->debugger.kill();
+}
+
+void BacktraceCollector::onDebuggerFinished(int exitCode, QProcess::ExitStatus /*exitStatus*/)
+{
+ if (d->errorOccurred) {
+ emit error(QLatin1String("QProcess: ") + d->debugger.errorString());
+ return;
+ }
+ if (exitCode != 0) {
+ emit error(QString::fromLatin1("Debugger exited with code %1.").arg(exitCode));
+ return;
+ }
+ emit backtrace(d->output);
+}
+
+void BacktraceCollector::onDebuggerError(QProcess::ProcessError /*error*/)
+{
+ d->errorOccurred = true;
+}
+
+QString BacktraceCollector::createTemporaryCommandFile()
+{
+ d->commandFile.reset(new QTemporaryFile);
+ if (!d->commandFile->open()) {
+ emit error(QLatin1String("Error: Could not create temporary command file."));
+ return QString();
+ }
+ if (d->commandFile->write(GdbBatchCommands) == -1) {
+ emit error(QLatin1String("Error: Could not write temporary command file."));
+ return QString();
+ }
+ d->commandFile->close();
+ return d->commandFile->fileName();
+}
+
+void BacktraceCollector::onDebuggerOutputAvailable()
+{
+ const QString newChunk = d->debugger.readAll();
+ d->output.append(newChunk);
+ emit backtraceChunk(newChunk);
+}
diff --git a/src/tools/qtcreatorcrashhandler/backtracecollector.h b/src/tools/qtcreatorcrashhandler/backtracecollector.h
new file mode 100644
index 0000000000..0fc14a4cd6
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/backtracecollector.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef BACKTRACECOLLECTOR_H
+#define BACKTRACECOLLECTOR_H
+
+#include <QProcess>
+
+class BacktraceCollectorPrivate;
+
+class BacktraceCollector : public QObject
+{
+ Q_OBJECT
+public:
+ explicit BacktraceCollector(QObject *parent = 0);
+ ~BacktraceCollector();
+
+ void run(Q_PID pid);
+ bool isRunning() const;
+ void kill();
+
+signals:
+ void error(const QString &errorMessage);
+ void backtrace(const QString &backtrace);
+ void backtraceChunk(const QString &chunk);
+
+private slots:
+ void onDebuggerOutputAvailable();
+ void onDebuggerFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void onDebuggerError(QProcess::ProcessError err);
+
+private:
+ QString createTemporaryCommandFile();
+
+ BacktraceCollectorPrivate *d;
+};
+
+#endif // BACKTRACECOLLECTOR_H
diff --git a/src/tools/qtcreatorcrashhandler/crashhandler.cpp b/src/tools/qtcreatorcrashhandler/crashhandler.cpp
new file mode 100644
index 0000000000..7521802716
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/crashhandler.cpp
@@ -0,0 +1,313 @@
+/**************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "crashhandler.h"
+#include "crashhandlerdialog.h"
+#include "backtracecollector.h"
+#include "utils.h"
+
+#include <utils/environment.h>
+
+#include <QApplication>
+#include <QDebug>
+#include <QDesktopServices>
+#include <QDir>
+#include <QFile>
+#include <QRegExp>
+#include <QTextStream>
+#include <QUrl>
+#include <QVector>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+static const char FileDistroInformation[] = "/etc/lsb-release";
+static const char FileKernelVersion[] = "/proc/version";
+static const char QtCreatorExecutable[] = "qtcreator";
+
+static QString collectLinuxDistributionInfo()
+{
+ return QString::fromLatin1(fileContents(QLatin1String(FileDistroInformation)));
+}
+
+static QString collectKernelVersionInfo()
+{
+ return QString::fromLatin1(fileContents(QLatin1String(FileKernelVersion)));
+}
+
+// Convience class for interacting with exec() family of functions.
+class CExecList : public QVector<char *>
+{
+public:
+ CExecList(const QStringList &list)
+ {
+ foreach (const QString &item, list)
+ append(qstrdup(item.toLatin1().data()));
+ append(0);
+ }
+
+ ~CExecList()
+ {
+ for (int i = 0; i < size(); ++i)
+ delete[] value(i);
+ }
+};
+
+class CrashHandlerPrivate
+{
+public:
+ CrashHandlerPrivate(pid_t pid, const QString &signalName, CrashHandler *crashHandler)
+ : pid(pid),
+ creatorInPath(Utils::Environment::systemEnvironment().searchInPath(QtCreatorExecutable)),
+ dialog(crashHandler, signalName) {}
+
+ const pid_t pid;
+ const QString creatorInPath; // Backup debugger.
+
+ BacktraceCollector backtraceCollector;
+ CrashHandlerDialog dialog;
+
+ QStringList restartAppCommandLine;
+ QStringList restartAppEnvironment;
+};
+
+CrashHandler::CrashHandler(pid_t pid, const QString &signalName, QObject *parent)
+ : QObject(parent), d(new CrashHandlerPrivate(pid, signalName, this))
+{
+ connect(&d->backtraceCollector, SIGNAL(error(QString)), SLOT(onError(QString)));
+ connect(&d->backtraceCollector, SIGNAL(backtraceChunk(QString)), SLOT(onBacktraceChunk(QString)));
+ connect(&d->backtraceCollector, SIGNAL(backtrace(QString)), SLOT(onBacktraceFinished(QString)));
+
+ d->dialog.appendDebugInfo(collectKernelVersionInfo());
+ d->dialog.appendDebugInfo(collectLinuxDistributionInfo());
+
+ if (!collectRestartAppData()) {
+ d->dialog.disableRestartAppCheckBox();
+ if (d->creatorInPath.isEmpty())
+ d->dialog.disableDebugAppButton();
+ }
+
+ d->dialog.show();
+}
+
+CrashHandler::~CrashHandler()
+{
+ delete d;
+}
+
+void CrashHandler::run()
+{
+ d->backtraceCollector.run(d->pid);
+}
+
+void CrashHandler::onError(const QString &errorMessage)
+{
+ d->dialog.setToFinalState();
+
+ QTextStream(stderr) << errorMessage;
+ const QString text = QLatin1String("There occured a problem providing the backtrace. "
+ "Please make sure to have the debugger \"gdb\" installed.\n");
+ d->dialog.appendDebugInfo(text);
+ d->dialog.appendDebugInfo(errorMessage);
+}
+
+void CrashHandler::onBacktraceChunk(const QString &chunk)
+{
+ d->dialog.appendDebugInfo(chunk);
+ QTextStream(stdout) << chunk;
+}
+
+void CrashHandler::onBacktraceFinished(const QString &backtrace)
+{
+ d->dialog.setToFinalState();
+
+ // Select first line of relevant thread.
+
+ // Example debugger output:
+ // ...
+ // [Current thread is 1 (Thread 0x7f1c33c79780 (LWP 975))]
+ // ...
+ // Thread 1 (Thread 0x7f1c33c79780 (LWP 975)):
+ // ...
+ QRegExp rx("\\[Current thread is (\\d+)");
+ const int pos = rx.indexIn(backtrace);
+ if (pos == -1)
+ return;
+ const QString threadNumber = rx.cap(1);
+ const QString textToSelect = QString::fromLatin1("Thread %1").arg(threadNumber);
+ d->dialog.selectLineWithContents(textToSelect);
+}
+
+void CrashHandler::openBugTracker()
+{
+ QDesktopServices::openUrl(QUrl(URL_BUGTRACKER));
+}
+
+bool CrashHandler::collectRestartAppData()
+{
+ const QString procDir = QString::fromLatin1("/proc/%1").arg(d->pid);
+
+ // Get command line.
+ // man 5 proc: /proc/[pid]/cmdline
+ // The command-line arguments appear in this file as a set of strings separated by
+ // null bytes ('\0'), with a further null byte after the last string.
+ const QString procCmdFileName = procDir + QLatin1String("/cmdline");
+ QList<QByteArray> commandLine = fileContents(procCmdFileName).split('\0');
+ if (commandLine.size() < 2) {
+ qWarning("%s: Unexpected format in file '%s'.\n", Q_FUNC_INFO, qPrintable(procCmdFileName));
+ return false;
+ }
+ commandLine.removeLast();
+ foreach (const QByteArray &item, commandLine)
+ d->restartAppCommandLine.append(QString::fromLatin1(item));
+
+ // Get environment.
+ // man 5 proc: /proc/[pid]/environ
+ // The entries are separated by null bytes ('\0'), and there may be a null byte at the end.
+ const QString procEnvFileName = procDir + QLatin1String("/environ");
+ QList<QByteArray> environment = fileContents(procEnvFileName).split('\0');
+ if (environment.isEmpty()) {
+ qWarning("%s: Unexpected format in file '%s'.\n", Q_FUNC_INFO, qPrintable(procEnvFileName));
+ return false;
+ }
+ if (environment.last().isEmpty())
+ environment.removeLast();
+ foreach (const QByteArray &item, environment)
+ d->restartAppEnvironment.append(QString::fromLatin1(item));
+
+ return true;
+}
+
+void CrashHandler::runCommand(QStringList commandLine, QStringList environment, WaitMode waitMode)
+{
+ // TODO: If QTBUG-2284 is resolved, use QProcess::startDetached() here.
+ // We can't use QProcess::startDetached because of bug
+ //
+ // QTBUG-2284
+ // QProcess::startDetached does not support setting an environment for the new process
+ //
+ // therefore, we use fork-exec.
+
+ pid_t pid = fork();
+ switch (pid) {
+ case -1: // error
+ qFatal("%s: fork() failed.", Q_FUNC_INFO);
+ break;
+ case 0: { // child
+ CExecList argv(commandLine);
+ CExecList envp(environment);
+ qDebug("Running\n");
+ for (int i = 0; argv[i]; ++i)
+ qDebug(" %s", argv[i]);
+ if (!environment.isEmpty()) {
+ qDebug("\nwith environment:\n");
+ for (int i = 0; envp[i]; ++i)
+ qDebug(" %s", envp[i]);
+ }
+
+ // The standards pipes must be open, otherwise the application will
+ // receive a SIGPIPE as soon as these are used.
+ if (freopen("/dev/null", "r", stdin) == 0)
+ qFatal("%s: freopen() failed for stdin: %s.\n", Q_FUNC_INFO, strerror(errno));
+ if (freopen("/dev/null", "w", stdout) == 0)
+ qFatal("%s: freopen() failed for stdout: %s.\n", Q_FUNC_INFO, strerror(errno));
+ if (freopen("/dev/null", "w", stderr) == 0)
+ qFatal("%s: freopen() failed for stderr: %s.\n.", Q_FUNC_INFO, strerror(errno));
+
+ if (environment.isEmpty())
+ execv(argv[0], argv.data());
+ else
+ execve(argv[0], argv.data(), envp.data());
+ _exit(EXIT_FAILURE);
+ } default: // parent
+ if (waitMode == WaitForExit) {
+ while (true) {
+ int status;
+ if (waitpid(pid, &status, 0) == -1) {
+ if (errno == EINTR) // Signal handler of QProcess for SIGCHLD was triggered.
+ continue;
+ perror("waitpid() failed unexpectedly");
+ }
+ if (WIFEXITED(status)) {
+ qDebug("Child exited with exit code %d.", WEXITSTATUS(status));
+ break;
+ } else if (WIFSIGNALED(status)) {
+ qDebug("Child terminated by signal %d.", WTERMSIG(status));
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+void CrashHandler::restartApplication()
+{
+ runCommand(d->restartAppCommandLine, d->restartAppEnvironment, DontWaitForExit);
+}
+
+void CrashHandler::debugApplication()
+{
+ // User requested to debug the app while our debugger is running.
+ if (d->backtraceCollector.isRunning()) {
+ if (!d->dialog.runDebuggerWhileBacktraceNotFinished())
+ return;
+ if (d->backtraceCollector.isRunning()) {
+ d->backtraceCollector.disconnect();
+ d->backtraceCollector.kill();
+ d->dialog.setToFinalState();
+ d->dialog.appendDebugInfo(tr("\n\nCollecting backtrace aborted by user."));
+ QCoreApplication::processEvents(); // Show the last appended output immediately.
+ }
+ }
+
+ // Prepare command.
+ QString executable = d->creatorInPath;
+ if (!d->restartAppCommandLine.isEmpty())
+ executable = d->restartAppCommandLine.at(0);
+ const QStringList commandLine = QStringList()
+ << executable
+ << QLatin1String("-debug")
+ << QString::number(d->pid);
+
+ QStringList environment;
+ if (!d->restartAppEnvironment.isEmpty())
+ environment = d->restartAppEnvironment;
+
+ // The UI is blocked/frozen anyway, so hide the dialog while debugging.
+ d->dialog.hide();
+ runCommand(commandLine, environment, WaitForExit);
+ d->dialog.show();
+}
diff --git a/src/tools/qtcreatorcrashhandler/crashhandler.h b/src/tools/qtcreatorcrashhandler/crashhandler.h
new file mode 100644
index 0000000000..bf4c1991da
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/crashhandler.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CRASHHANDLER_H
+#define CRASHHANDLER_H
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+class QString;
+QT_END_NAMESPACE
+
+class ApplicationInfo;
+class CrashHandlerPrivate;
+
+class CrashHandler : public QObject
+{
+ Q_OBJECT
+public:
+ explicit CrashHandler(pid_t pid, const QString &signalName, QObject *parent = 0);
+ ~CrashHandler();
+
+ void run();
+
+public slots:
+ void onError(const QString &errorMessage);
+ void onBacktraceChunk(const QString &chunk);
+ void onBacktraceFinished(const QString &backtrace);
+
+ void openBugTracker();
+ void restartApplication();
+ void debugApplication();
+
+private:
+ bool collectRestartAppData();
+
+ enum WaitMode { WaitForExit, DontWaitForExit };
+ static void runCommand(QStringList commandLine, QStringList environment, WaitMode waitMode);
+
+ CrashHandlerPrivate *d;
+};
+
+#endif // CRASHHANDLER_H
diff --git a/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp
new file mode 100644
index 0000000000..5d23255753
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp
@@ -0,0 +1,180 @@
+/**************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "crashhandler.h"
+#include "crashhandlerdialog.h"
+#include "ui_crashhandlerdialog.h"
+#include "utils.h"
+
+#include <app/app_version.h>
+#include <utils/checkablemessagebox.h>
+
+#include <QClipboard>
+#include <QIcon>
+#include <QSettings>
+
+static const char SettingsApplication[] = "QtCreator";
+static const char SettingsKeySkipWarningAbortingBacktrace[]
+ = "CrashHandler/SkipWarningAbortingBacktrace";
+
+CrashHandlerDialog::CrashHandlerDialog(CrashHandler *handler, const QString &signalName,
+ QWidget *parent) :
+ QDialog(parent),
+ m_crashHandler(handler),
+ m_ui(new Ui::CrashHandlerDialog)
+{
+ m_ui->setupUi(this);
+ m_ui->introLabel->setTextFormat(Qt::RichText);
+ m_ui->introLabel->setOpenExternalLinks(true);
+ m_ui->debugInfoEdit->setReadOnly(true);
+ m_ui->progressBar->setMinimum(0);
+ m_ui->progressBar->setMaximum(0);
+
+ const QStyle * const style = QApplication::style();
+ m_ui->closeButton->setIcon(style->standardIcon(QStyle::SP_DialogCloseButton));
+
+ const int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, 0);
+ QIcon icon = style->standardIcon(QStyle::SP_MessageBoxCritical);
+ m_ui->iconLabel->setPixmap(icon.pixmap(iconSize, iconSize));
+
+ connect(m_ui->copyToClipBoardButton, SIGNAL(clicked()), this, SLOT(copyToClipboardClicked()));
+ connect(m_ui->reportBugButton, SIGNAL(clicked()), m_crashHandler, SLOT(openBugTracker()));
+ connect(m_ui->debugAppButton, SIGNAL(clicked()), m_crashHandler, SLOT(debugApplication()));
+ connect(m_ui->closeButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ setApplicationInfo(signalName);
+}
+
+CrashHandlerDialog::~CrashHandlerDialog()
+{
+ delete m_ui;
+}
+
+bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
+{
+ // Check settings.
+ QSettings settings(QSettings::IniFormat, QSettings::UserScope,
+ QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
+ QLatin1String(SettingsApplication));
+ if (settings.value(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), false).toBool())
+ return true;
+
+ // Ask user.
+ const QString title = tr("Run Debugger And Abort Collecting Backtrace?");
+ const QString message = tr(
+ "<html><head/><body>"
+ "<p><b>Run the debugger and abort collecting backtrace?</b></p>"
+ "<p>You have requested to run the debugger while collecting the backtrace was not "
+ "finished.</p>"
+ "</body></html>");
+ const QString checkBoxText = tr("Do not &ask again.");
+ bool checkBoxSetting = false;
+ const QDialogButtonBox::StandardButton button = Utils::CheckableMessageBox::question(this,
+ title, message, checkBoxText, &checkBoxSetting,
+ QDialogButtonBox::Yes|QDialogButtonBox::No, QDialogButtonBox::No);
+ if (checkBoxSetting)
+ settings.setValue(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), checkBoxSetting);
+
+ return button == QDialogButtonBox::Yes;
+}
+
+void CrashHandlerDialog::setToFinalState()
+{
+ m_ui->progressBar->hide();
+ m_ui->copyToClipBoardButton->setEnabled(true);
+ m_ui->reportBugButton->setEnabled(true);
+}
+
+void CrashHandlerDialog::disableRestartAppCheckBox()
+{
+ m_ui->restartAppCheckBox->setDisabled(true);
+}
+
+void CrashHandlerDialog::disableDebugAppButton()
+{
+ m_ui->debugAppButton->setDisabled(true);
+}
+
+void CrashHandlerDialog::setApplicationInfo(const QString &signalName)
+{
+ const QString ideName = QLatin1String("Qt Creator");
+ const QString title = tr("%1 has closed unexpectedly (Signal \"%2\")").arg(ideName, signalName);
+ 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>")
+ .arg(title, QLatin1String(URL_BUGTRACKER));
+ m_ui->introLabel->setText(introLabelContents);
+ setWindowTitle(title);
+
+ QString revision;
+#ifdef IDE_REVISION
+ revision = tr(" from revision %1").arg(QString::fromLatin1(Core::Constants::IDE_REVISION_STR).left(10));
+#endif
+ const QString versionInformation = tr(
+ "%1 %2%3, built on %4 at %5, based on Qt %6 (%7 bit)\n")
+ .arg(ideName, QLatin1String(Core::Constants::IDE_VERSION_LONG), revision,
+ QLatin1String(__DATE__), QLatin1String(__TIME__), QLatin1String(QT_VERSION_STR),
+ QString::number(QSysInfo::WordSize));
+ m_ui->debugInfoEdit->append(versionInformation);
+}
+
+void CrashHandlerDialog::appendDebugInfo(const QString &chunk)
+{
+ m_ui->debugInfoEdit->append(chunk);
+}
+
+void CrashHandlerDialog::selectLineWithContents(const QString &text)
+{
+ // The selected line will be the first line visible.
+
+ // Go to end.
+ QTextCursor cursor = m_ui->debugInfoEdit->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ m_ui->debugInfoEdit->setTextCursor(cursor);
+
+ // Find text by searching backwards.
+ m_ui->debugInfoEdit->find(text, QTextDocument::FindCaseSensitively | QTextDocument::FindBackward);
+
+ // Highlight whole line.
+ cursor = m_ui->debugInfoEdit->textCursor();
+ cursor.select(QTextCursor::LineUnderCursor);
+ m_ui->debugInfoEdit->setTextCursor(cursor);
+}
+
+void CrashHandlerDialog::copyToClipboardClicked()
+{
+ QApplication::clipboard()->setText(m_ui->debugInfoEdit->toPlainText());
+}
+
+void CrashHandlerDialog::close()
+{
+ if (m_ui->restartAppCheckBox->isEnabled() && m_ui->restartAppCheckBox->isChecked())
+ m_crashHandler->restartApplication();
+ qApp->quit();
+}
diff --git a/src/tools/qtcreatorcrashhandler/crashhandlerdialog.h b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.h
new file mode 100644
index 0000000000..fc9ff7921a
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CRASHHANDLERDIALOG_H
+#define CRASHHANDLERDIALOG_H
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+class QString;
+namespace Ui {
+class CrashHandlerDialog;
+}
+QT_END_NAMESPACE
+
+class CrashHandler;
+
+class CrashHandlerDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit CrashHandlerDialog(CrashHandler *handler, const QString &signalName,
+ QWidget *parent = 0);
+ ~CrashHandlerDialog();
+
+public:
+ void setApplicationInfo(const QString &signalName);
+ void appendDebugInfo(const QString &chunk);
+ void selectLineWithContents(const QString &text);
+ void setToFinalState();
+ void disableRestartAppCheckBox();
+ void disableDebugAppButton();
+ bool runDebuggerWhileBacktraceNotFinished();
+
+private slots:
+ void copyToClipboardClicked();
+ void close();
+
+private:
+ CrashHandler *m_crashHandler;
+ Ui::CrashHandlerDialog *m_ui;
+};
+
+#endif // CRASHHANDLERDIALOG_H
diff --git a/src/tools/qtcreatorcrashhandler/crashhandlerdialog.ui b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.ui
new file mode 100644
index 0000000000..9a7b67a003
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.ui
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CrashHandlerDialog</class>
+ <widget class="QDialog" name="CrashHandlerDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>800</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>500</width>
+ <height>300</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item>
+ <widget class="QLabel" name="iconLabel">
+ <property name="text">
+ <string>Icon</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="introLabel">
+ <property name="text">
+ <string>Some useful information here...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressBar">
+ <property name="value">
+ <number>24</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextEdit" name="debugInfoEdit"/>
+ </item>
+ <item alignment="Qt::AlignRight">
+ <widget class="QCheckBox" name="restartAppCheckBox">
+ <property name="text">
+ <string>&amp;Restart Qt Creator on close</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="copyToClipBoardButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Copy the whole contents to clipboard.</string>
+ </property>
+ <property name="text">
+ <string>C&amp;opy to clipboard</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="reportBugButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Open the bug tracker web site.</string>
+ </property>
+ <property name="text">
+ <string>Report this &amp;bug</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="debugAppButton">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip">
+ <string>Debug the application with a new instance of Qt Creator. During debugging the crash handler will be hidden.</string>
+ </property>
+ <property name="text">
+ <string>Attach and &amp;Debug</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="closeButton">
+ <property name="toolTip">
+ <string>Quit the handler and the crashed application.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/tools/qtcreatorcrashhandler/crashhandlersetup.cpp b/src/tools/qtcreatorcrashhandler/crashhandlersetup.cpp
new file mode 100644
index 0000000000..cc48afa731
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/crashhandlersetup.cpp
@@ -0,0 +1,134 @@
+/**************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "crashhandlersetup.h"
+
+#include <QtGlobal>
+
+#if !defined(QT_NO_DEBUG) && defined(Q_OS_LINUX)
+#define BUILD_CRASH_HANDLER
+#endif
+
+#ifdef BUILD_CRASH_HANDLER
+
+#include <QApplication>
+#include <QDebug>
+#include <QString>
+
+#include <stdlib.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#ifdef Q_WS_X11
+#include <qx11info_x11.h>
+#include <X11/Xlib.h>
+#endif
+
+static const char *crashHandlerPathC;
+static void *signalHandlerStack;
+
+extern "C" void signalHandler(int signal)
+{
+#ifdef Q_WS_X11
+ // Kill window since it's frozen anyway.
+ if (QX11Info::display())
+ close(ConnectionNumber(QX11Info::display()));
+#endif
+ pid_t pid = fork();
+ switch (pid) {
+ case -1: // error
+ break;
+ case 0: // child
+ execl(crashHandlerPathC, crashHandlerPathC, strsignal(signal), (char *) 0);
+ _exit(EXIT_FAILURE);
+ default: // parent
+ waitpid(pid, 0, 0);
+ _exit(EXIT_FAILURE);
+ break;
+ }
+}
+#endif // BUILD_CRASH_HANDLER
+
+void setupCrashHandler()
+{
+#ifdef BUILD_CRASH_HANDLER
+ const QString crashHandlerPath = qApp->applicationDirPath()
+ + QLatin1String("/qtcreator_crash_handler");
+ crashHandlerPathC = qstrdup(qPrintable(crashHandlerPath));
+
+ // Setup an alternative stack for the signal handler. This way we are able to handle SIGSEGV
+ // even if the normal process stack is exhausted.
+ stack_t ss;
+ ss.ss_sp = signalHandlerStack = malloc(SIGSTKSZ); // Usual requirements for alternative signal stack.
+ if (ss.ss_sp == 0) {
+ qWarning("Warning: Could not allocate space for alternative signal stack (%s).", Q_FUNC_INFO);
+ return;
+ }
+ ss.ss_size = SIGSTKSZ;
+ ss.ss_flags = 0;
+ if (sigaltstack(&ss, 0) == -1) {
+ qWarning("Warning: Failed to set alternative signal stack (%s).", Q_FUNC_INFO);
+ return;
+ }
+
+ // Install signal handler for calling the crash handler.
+ struct sigaction sa;
+ if (sigemptyset(&sa.sa_mask) == -1) {
+ qWarning("Warning: Failed to empty signal set (%s).", Q_FUNC_INFO);
+ return;
+ }
+ sa.sa_handler = &signalHandler;
+ // SA_RESETHAND - Restore signal action to default after signal handler has been called.
+ // SA_NODEFER - Don't block the signal after it was triggered (otherwise blocked signals get
+ // inherited via fork() and execve()). Without this the signal will not be delivered to the
+ // restarted Qt Creator.
+ // SA_ONSTACK - Use alternative stack.
+ sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_ONSTACK;
+ const int signalsToHandle[] = { SIGILL, SIGFPE, SIGSEGV, SIGBUS, 0 };
+ for (int i = 0; signalsToHandle[i]; ++i) {
+ if (sigaction(signalsToHandle[i], &sa, 0) == -1 ) {
+ qWarning("Warning: Failed to install signal handler for signal \"%s\" (%s).",
+ strsignal(signalsToHandle[i]), Q_FUNC_INFO);
+ }
+ }
+#endif // BUILD_CRASH_HANDLER
+}
+
+void cleanupCrashHandler()
+{
+#ifdef BUILD_CRASH_HANDLER
+ delete[] crashHandlerPathC;
+ free(signalHandlerStack);
+#endif
+}
diff --git a/src/tools/qtcreatorcrashhandler/crashhandlersetup.h b/src/tools/qtcreatorcrashhandler/crashhandlersetup.h
new file mode 100644
index 0000000000..02c50ef230
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/crashhandlersetup.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CRASHHANDLERSETUP_H
+#define CRASHHANDLERSETUP_H
+
+void setupCrashHandler();
+void cleanupCrashHandler();
+
+#endif // CRASHHANDLERSETUP_H
diff --git a/src/tools/qtcreatorcrashhandler/main.cpp b/src/tools/qtcreatorcrashhandler/main.cpp
new file mode 100644
index 0000000000..623520cf22
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/main.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "crashhandler.h"
+#include "utils.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QProcess>
+#include <QString>
+#include <QStyle>
+#include <QTextStream>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// Called by signal handler of qtcreator.
+// Usage: $0 <name of signal causing the crash>
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ app.setApplicationName(QLatin1String(APPLICATION_NAME));
+ app.setWindowIcon(QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical));
+
+ // Check usage.
+ Q_PID parentPid = getppid();
+ QString parentExecutable = QFile::symLinkTarget(QString::fromLatin1("/proc/%1/exe")
+ .arg(QString::number(parentPid)));
+ if (argc > 2 || !parentExecutable.contains("qtcreator")) {
+ QTextStream err(stderr);
+ err << QString::fromLatin1("This crash handler will be called by Qt Creator itself. "
+ "Do not call this manually.\n");
+ return EXIT_FAILURE;
+ }
+
+ // Run.
+ CrashHandler *crashHandler = new CrashHandler(parentPid, app.arguments().at(1));
+ crashHandler->run();
+
+ return app.exec();
+}
diff --git a/src/tools/qtcreatorcrashhandler/qtcreatorcrashhandler.pro b/src/tools/qtcreatorcrashhandler/qtcreatorcrashhandler.pro
new file mode 100644
index 0000000000..bfcb41e303
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/qtcreatorcrashhandler.pro
@@ -0,0 +1,31 @@
+include(../../../qtcreator.pri)
+
+TARGET = qtcreator_crash_handler
+DESTDIR = $$IDE_BIN_PATH
+
+CONFIG -= app_bundle
+TEMPLATE = app
+
+SOURCES += \
+ main.cpp \
+ backtracecollector.cpp \
+ crashhandlerdialog.cpp \
+ crashhandler.cpp \
+ utils.cpp \
+ ../../libs/utils/checkablemessagebox.cpp \
+ ../../libs/utils/environment.cpp
+
+
+HEADERS += \
+ backtracecollector.h \
+ crashhandlerdialog.h \
+ crashhandler.h \
+ utils.h \
+ ../../libs/utils/checkablemessagebox.h \
+ ../../libs/utils/environment.h
+
+FORMS += \
+ crashhandlerdialog.ui
+
+target.path = /bin
+INSTALLS += target
diff --git a/src/tools/qtcreatorcrashhandler/qtcreatorcrashhandler.qbs b/src/tools/qtcreatorcrashhandler/qtcreatorcrashhandler.qbs
new file mode 100644
index 0000000000..35d6187d56
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/qtcreatorcrashhandler.qbs
@@ -0,0 +1,33 @@
+import qbs.base 1.0
+import "../QtcTool.qbs" as QtcTool
+
+QtcTool {
+ name: "qtcreator_crash_handler"
+ condition: qbs.targetOS == "linux" && qbs.buildVariant == "debug"
+
+ cpp.includePaths: [
+ buildDirectory,
+ "../../libs"
+ ]
+
+ Depends { name: "cpp" }
+ Depends { name: "Qt.widgets" }
+ Depends { name: "app_version_header" }
+
+ files: [
+ "../../libs/utils/checkablemessagebox.cpp",
+ "../../libs/utils/checkablemessagebox.h",
+ "../../libs/utils/environment.cpp",
+ "../../libs/utils/environment.h",
+ "backtracecollector.cpp",
+ "backtracecollector.h",
+ "crashhandler.cpp",
+ "crashhandler.h",
+ "crashhandlerdialog.cpp",
+ "crashhandlerdialog.h",
+ "crashhandlerdialog.ui",
+ "main.cpp",
+ "utils.cpp",
+ "utils.h"
+ ]
+}
diff --git a/src/tools/qtcreatorcrashhandler/utils.cpp b/src/tools/qtcreatorcrashhandler/utils.cpp
new file mode 100644
index 0000000000..2fe505b1f8
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/utils.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "utils.h"
+
+#include <QDebug>
+#include <QFile>
+
+QByteArray fileContents(const QString &filePath)
+{
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning("Warning: Could not open '%s'.", qPrintable(filePath));
+ return QByteArray();
+ }
+ return file.readAll();
+}
diff --git a/src/tools/qtcreatorcrashhandler/utils.h b/src/tools/qtcreatorcrashhandler/utils.h
new file mode 100644
index 0000000000..0232db5ca1
--- /dev/null
+++ b/src/tools/qtcreatorcrashhandler/utils.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <QByteArray>
+#include <QString>
+
+const char APPLICATION_NAME[] = "Qt Creator Crash Handler";
+const char URL_BUGTRACKER[] = "https://bugreports.qt-project.org/";
+
+QByteArray fileContents(const QString &filePath);
+
+#endif // UTILS_H
diff --git a/src/tools/sdktool/sdktool.qbs b/src/tools/sdktool/sdktool.qbs
index 1ecea9e4c1..7d8e571a90 100644
--- a/src/tools/sdktool/sdktool.qbs
+++ b/src/tools/sdktool/sdktool.qbs
@@ -4,17 +4,16 @@ import "../QtcTool.qbs" as QtcTool
QtcTool {
name: "sdktool"
- cpp.includePaths: [buildDirectory]
- cpp.defines: base.concat([qbs.targetOS === "mac"
- ? 'DATA_PATH="."' : 'DATA_PATH="../share/qtcreator"'])
-
Depends { name: "cpp" }
Depends { name: "Qt.core" }
Depends { name: "Utils" }
Depends { name: "app_version_header" }
+ cpp.includePaths: "../../libs"
+ cpp.defines: base.concat([qbs.targetOS === "mac"
+ ? 'DATA_PATH="."' : 'DATA_PATH="../share/qtcreator"'])
+
files: [
- "main.cpp",
"addkeysoperation.cpp",
"addkeysoperation.h",
"addkitoperation.cpp",
@@ -29,8 +28,9 @@ QtcTool {
"findvalueoperation.h",
"getoperation.cpp",
"getoperation.h",
- "operation.h",
+ "main.cpp",
"operation.cpp",
+ "operation.h",
"rmkeysoperation.cpp",
"rmkeysoperation.h",
"rmkitoperation.cpp",
@@ -40,6 +40,6 @@ QtcTool {
"rmtoolchainoperation.cpp",
"rmtoolchainoperation.h",
"settings.cpp",
- "settings.h"
+ "settings.h",
]
}
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
index 1f499584d5..3a48a7918f 100644
--- a/src/tools/tools.pro
+++ b/src/tools/tools.pro
@@ -2,6 +2,7 @@ TEMPLATE = subdirs
SUBDIRS = qtpromaker \
qmlpuppet \
+ ../plugins/cpaster/frontend \
sdktool
win32 {
@@ -21,5 +22,11 @@ win32 {
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
!isEmpty(QT_BREAKPAD_ROOT_PATH) {
SUBDIRS += qtcrashhandler
+} else {
+ linux-* {
+ # Build only in debug mode.
+ debug_and_release|CONFIG(debug, debug|release) {
+ SUBDIRS += qtcreatorcrashhandler
+ }
+ }
}
-