From ecf5bd3c4fd8557b06c6849b317d8d3ccaca528f Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sun, 22 May 2016 13:12:02 +0200 Subject: A better crashhandler that notifies the client of the crash. --- common/listener.cpp | 17 ++++++++++++ common/listener.h | 1 + common/resourceaccess.cpp | 6 +++- synchronizer/main.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/common/listener.cpp b/common/listener.cpp index 28748e5..de20b2c 100644 --- a/common/listener.cpp +++ b/common/listener.cpp @@ -87,6 +87,23 @@ Listener::~Listener() { } +void Listener::emergencyAbortAllConnections() +{ + for (Client &client : m_connections) { + if (client.socket) { + Warning() << "Sending panic"; + client.socket->write("PANIC"); + client.socket->waitForBytesWritten(); + disconnect(client.socket, 0, this, 0); + client.socket->abort(); + delete client.socket; + client.socket = 0; + } + } + + m_connections.clear(); +} + void Listener::closeAllConnections() { for (Client &client : m_connections) { diff --git a/common/listener.h b/common/listener.h index cd1a7f6..5e376c7 100644 --- a/common/listener.h +++ b/common/listener.h @@ -64,6 +64,7 @@ signals: public slots: void closeAllConnections(); + void emergencyAbortAllConnections(); private slots: void acceptConnection(); diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp index 458694f..991c930 100644 --- a/common/resourceaccess.cpp +++ b/common/resourceaccess.cpp @@ -474,7 +474,11 @@ void ResourceAccess::disconnected() void ResourceAccess::connectionError(QLocalSocket::LocalSocketError error) { - if (error == QLocalSocket::PeerClosedError) { + const bool resourceCrashed = d->partialMessageBuffer.contains("PANIC"); + if (resourceCrashed) { + ErrorMsg() << "The resource crashed!"; + d->abortPendingOperations(); + } else if (error == QLocalSocket::PeerClosedError) { Log() << "The resource closed the connection."; d->abortPendingOperations(); } else { diff --git a/synchronizer/main.cpp b/synchronizer/main.cpp index 179fbf5..e000e03 100644 --- a/synchronizer/main.cpp +++ b/synchronizer/main.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include +#include #include "listener.h" #include "log.h" @@ -29,10 +32,10 @@ #undef DEBUG_AREA #define DEBUG_AREA "resource" -void crashHandler(int sig) -{ - std::fprintf(stderr, "Error: signal %d\n", sig); +Listener *listener = nullptr; +void printStacktrace() +{ QString s; void *trace[256]; int n = backtrace(trace, 256); @@ -51,18 +54,73 @@ void crashHandler(int sig) free(strings); } } +} + +int sCounter = 0; + +void crashHandler(int signal) +{ + //Guard against crashing in here + if (sCounter > 1) { + std::_Exit(EXIT_FAILURE); + return; + } + sCounter++; + + if (signal == SIGABRT) { + std::cerr << "SIGABRT received\n"; + } else if (signal == SIGSEGV) { + std::cerr << "SIGSEV received\n"; + } else { + std::cerr << "Unexpected signal " << signal << " received\n"; + } + + printStacktrace(); + + //Get the word out that we're going down + listener->emergencyAbortAllConnections(); - std::system("exec gdb -p \"$PPID\" -ex \"thread apply all bt\""); + // std::system("exec gdb -p \"$PPID\" -ex \"thread apply all bt\""); // This only works if we actually have xterm and X11 available // std::system("exec xterm -e gdb -p \"$PPID\""); + std::_Exit(EXIT_FAILURE); + return; +} + +void terminateHandler() +{ + std::exception_ptr exptr = std::current_exception(); + if (exptr != 0) + { + // the only useful feature of std::exception_ptr is that it can be rethrown... + try + { + std::rethrow_exception(exptr); + } + catch (std::exception &ex) + { + std::fprintf(stderr, "Terminated due to exception: %s\n", ex.what()); + } + catch (...) + { + std::fprintf(stderr, "Terminated due to unknown exception\n"); + } + } + else + { + std::fprintf(stderr, "Terminated due to unknown reason :(\n"); + } std::abort(); } int main(int argc, char *argv[]) { // For crashes - signal(SIGSEGV, crashHandler); + std::signal(SIGSEGV, crashHandler); + std::signal(SIGABRT, crashHandler); + std::set_terminate(terminateHandler); + QCoreApplication app(argc, argv); if (argc < 3) { @@ -81,7 +139,7 @@ int main(int argc, char *argv[]) return -1; } - Listener *listener = new Listener(instanceIdentifier, resourceType, &app); + listener = new Listener(instanceIdentifier, resourceType, &app); QObject::connect(&app, &QCoreApplication::aboutToQuit, listener, &Listener::closeAllConnections); QObject::connect(listener, &Listener::noClients, &app, &QCoreApplication::quit); -- cgit v1.2.3