diff options
author | Peter Varga <pvarga@inf.u-szeged.hu> | 2017-03-06 16:15:17 +0100 |
---|---|---|
committer | Peter Varga <pvarga@inf.u-szeged.hu> | 2017-03-08 09:37:10 +0000 |
commit | 44cb79ed88152d93d418b0ee1c101da8e05069a7 (patch) | |
tree | 09adced26232a936379243af28090127c989993e /tests | |
parent | d2b9edf8a94ef76ce2bcb0ff1cb32d62616df3e1 (diff) |
Add SIGSEGV handler for the QML tests on Linux
The new handler prints stack trace if the browser process crashes due to
segmentation fault while running QML tests. The solution is based on the
QTestLib signal handler implementation.
Change-Id: I5ccffc92043375fbf6fa5805a4592c61603efb3f
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/quick/qmltests/tst_qmltests.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/tests/auto/quick/qmltests/tst_qmltests.cpp b/tests/auto/quick/qmltests/tst_qmltests.cpp index baffdbb57..5dc909709 100644 --- a/tests/auto/quick/qmltests/tst_qmltests.cpp +++ b/tests/auto/quick/qmltests/tst_qmltests.cpp @@ -31,8 +31,82 @@ #include <QtWebEngine/QQuickWebEngineProfile> #include "qt_webengine_quicktest.h" +#if defined(Q_OS_LINUX) && defined(QT_DEBUG) +#include <fcntl.h> +#include <signal.h> +#include <unistd.h> +#endif + +#if defined(Q_OS_LINUX) && defined(QT_DEBUG) +static bool debuggerPresent() +{ + int fd = open("/proc/self/status", O_RDONLY); + if (fd == -1) + return false; + char buffer[2048]; + ssize_t size = read(fd, buffer, sizeof(buffer) - 1); + if (size == -1) { + close(fd); + return false; + } + buffer[size] = 0; + const char tracerPidToken[] = "\nTracerPid:"; + char *tracerPid = strstr(buffer, tracerPidToken); + if (!tracerPid) { + close(fd); + return false; + } + tracerPid += sizeof(tracerPidToken); + long int pid = strtol(tracerPid, &tracerPid, 10); + close(fd); + return pid != 0; +} + +static void stackTrace() +{ + bool ok = false; + const int disableStackDump = qEnvironmentVariableIntValue("QTEST_DISABLE_STACK_DUMP", &ok); + if (ok && disableStackDump == 1) + return; + + if (debuggerPresent()) + return; + + fprintf(stderr, "\n========= Received signal, dumping stack ==============\n"); + char cmd[512]; + qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null <<EOF\n" + "set prompt\n" + "set height 0\n" + "thread apply all where full\n" + "detach\n" + "quit\n" + "EOF\n", + (int)getpid()); + + if (system(cmd) == -1) + fprintf(stderr, "calling gdb failed\n"); + fprintf(stderr, "========= End of stack trace ==============\n"); +} + +static void sigSegvHandler(int signum) +{ + stackTrace(); + qFatal("Received signal %d", signum); +} +#endif + int main(int argc, char **argv) { +#if defined(Q_OS_LINUX) && defined(QT_DEBUG) + struct sigaction sigAction; + + sigemptyset(&sigAction.sa_mask); + sigAction.sa_handler = &sigSegvHandler; + sigAction.sa_flags = 0; + + sigaction(SIGSEGV, &sigAction, 0); +#endif + // Inject the mock ui delegates module qputenv("QML2_IMPORT_PATH", QByteArray(TESTS_SOURCE_DIR "qmltests/mock-delegates")); QScopedPointer<Application> app; |