diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-05-22 13:12:02 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-05-22 13:12:02 +0200 |
commit | ecf5bd3c4fd8557b06c6849b317d8d3ccaca528f (patch) | |
tree | 6d7d038b6d705356040e8b1f331c075f90b7c690 | |
parent | 6864e4accaafa4fa90332719bff5a85a0e92b242 (diff) | |
download | sink-ecf5bd3c4fd8557b06c6849b317d8d3ccaca528f.tar.gz sink-ecf5bd3c4fd8557b06c6849b317d8d3ccaca528f.zip |
A better crashhandler that notifies the client of the crash.
-rw-r--r-- | common/listener.cpp | 17 | ||||
-rw-r--r-- | common/listener.h | 1 | ||||
-rw-r--r-- | common/resourceaccess.cpp | 6 | ||||
-rw-r--r-- | 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() | |||
87 | { | 87 | { |
88 | } | 88 | } |
89 | 89 | ||
90 | void Listener::emergencyAbortAllConnections() | ||
91 | { | ||
92 | for (Client &client : m_connections) { | ||
93 | if (client.socket) { | ||
94 | Warning() << "Sending panic"; | ||
95 | client.socket->write("PANIC"); | ||
96 | client.socket->waitForBytesWritten(); | ||
97 | disconnect(client.socket, 0, this, 0); | ||
98 | client.socket->abort(); | ||
99 | delete client.socket; | ||
100 | client.socket = 0; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | m_connections.clear(); | ||
105 | } | ||
106 | |||
90 | void Listener::closeAllConnections() | 107 | void Listener::closeAllConnections() |
91 | { | 108 | { |
92 | for (Client &client : m_connections) { | 109 | 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: | |||
64 | 64 | ||
65 | public slots: | 65 | public slots: |
66 | void closeAllConnections(); | 66 | void closeAllConnections(); |
67 | void emergencyAbortAllConnections(); | ||
67 | 68 | ||
68 | private slots: | 69 | private slots: |
69 | void acceptConnection(); | 70 | 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() | |||
474 | 474 | ||
475 | void ResourceAccess::connectionError(QLocalSocket::LocalSocketError error) | 475 | void ResourceAccess::connectionError(QLocalSocket::LocalSocketError error) |
476 | { | 476 | { |
477 | if (error == QLocalSocket::PeerClosedError) { | 477 | const bool resourceCrashed = d->partialMessageBuffer.contains("PANIC"); |
478 | if (resourceCrashed) { | ||
479 | ErrorMsg() << "The resource crashed!"; | ||
480 | d->abortPendingOperations(); | ||
481 | } else if (error == QLocalSocket::PeerClosedError) { | ||
478 | Log() << "The resource closed the connection."; | 482 | Log() << "The resource closed the connection."; |
479 | d->abortPendingOperations(); | 483 | d->abortPendingOperations(); |
480 | } else { | 484 | } 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 @@ | |||
22 | 22 | ||
23 | #include <signal.h> | 23 | #include <signal.h> |
24 | #include <execinfo.h> | 24 | #include <execinfo.h> |
25 | #include <csignal> | ||
26 | #include <iostream> | ||
27 | #include <cstdlib> | ||
25 | 28 | ||
26 | #include "listener.h" | 29 | #include "listener.h" |
27 | #include "log.h" | 30 | #include "log.h" |
@@ -29,10 +32,10 @@ | |||
29 | #undef DEBUG_AREA | 32 | #undef DEBUG_AREA |
30 | #define DEBUG_AREA "resource" | 33 | #define DEBUG_AREA "resource" |
31 | 34 | ||
32 | void crashHandler(int sig) | 35 | Listener *listener = nullptr; |
33 | { | ||
34 | std::fprintf(stderr, "Error: signal %d\n", sig); | ||
35 | 36 | ||
37 | void printStacktrace() | ||
38 | { | ||
36 | QString s; | 39 | QString s; |
37 | void *trace[256]; | 40 | void *trace[256]; |
38 | int n = backtrace(trace, 256); | 41 | int n = backtrace(trace, 256); |
@@ -51,18 +54,73 @@ void crashHandler(int sig) | |||
51 | free(strings); | 54 | free(strings); |
52 | } | 55 | } |
53 | } | 56 | } |
57 | } | ||
58 | |||
59 | int sCounter = 0; | ||
60 | |||
61 | void crashHandler(int signal) | ||
62 | { | ||
63 | //Guard against crashing in here | ||
64 | if (sCounter > 1) { | ||
65 | std::_Exit(EXIT_FAILURE); | ||
66 | return; | ||
67 | } | ||
68 | sCounter++; | ||
69 | |||
70 | if (signal == SIGABRT) { | ||
71 | std::cerr << "SIGABRT received\n"; | ||
72 | } else if (signal == SIGSEGV) { | ||
73 | std::cerr << "SIGSEV received\n"; | ||
74 | } else { | ||
75 | std::cerr << "Unexpected signal " << signal << " received\n"; | ||
76 | } | ||
77 | |||
78 | printStacktrace(); | ||
79 | |||
80 | //Get the word out that we're going down | ||
81 | listener->emergencyAbortAllConnections(); | ||
54 | 82 | ||
55 | std::system("exec gdb -p \"$PPID\" -ex \"thread apply all bt\""); | 83 | // std::system("exec gdb -p \"$PPID\" -ex \"thread apply all bt\""); |
56 | // This only works if we actually have xterm and X11 available | 84 | // This only works if we actually have xterm and X11 available |
57 | // std::system("exec xterm -e gdb -p \"$PPID\""); | 85 | // std::system("exec xterm -e gdb -p \"$PPID\""); |
58 | 86 | ||
87 | std::_Exit(EXIT_FAILURE); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | void terminateHandler() | ||
92 | { | ||
93 | std::exception_ptr exptr = std::current_exception(); | ||
94 | if (exptr != 0) | ||
95 | { | ||
96 | // the only useful feature of std::exception_ptr is that it can be rethrown... | ||
97 | try | ||
98 | { | ||
99 | std::rethrow_exception(exptr); | ||
100 | } | ||
101 | catch (std::exception &ex) | ||
102 | { | ||
103 | std::fprintf(stderr, "Terminated due to exception: %s\n", ex.what()); | ||
104 | } | ||
105 | catch (...) | ||
106 | { | ||
107 | std::fprintf(stderr, "Terminated due to unknown exception\n"); | ||
108 | } | ||
109 | } | ||
110 | else | ||
111 | { | ||
112 | std::fprintf(stderr, "Terminated due to unknown reason :(\n"); | ||
113 | } | ||
59 | std::abort(); | 114 | std::abort(); |
60 | } | 115 | } |
61 | 116 | ||
62 | int main(int argc, char *argv[]) | 117 | int main(int argc, char *argv[]) |
63 | { | 118 | { |
64 | // For crashes | 119 | // For crashes |
65 | signal(SIGSEGV, crashHandler); | 120 | std::signal(SIGSEGV, crashHandler); |
121 | std::signal(SIGABRT, crashHandler); | ||
122 | std::set_terminate(terminateHandler); | ||
123 | |||
66 | QCoreApplication app(argc, argv); | 124 | QCoreApplication app(argc, argv); |
67 | 125 | ||
68 | if (argc < 3) { | 126 | if (argc < 3) { |
@@ -81,7 +139,7 @@ int main(int argc, char *argv[]) | |||
81 | return -1; | 139 | return -1; |
82 | } | 140 | } |
83 | 141 | ||
84 | Listener *listener = new Listener(instanceIdentifier, resourceType, &app); | 142 | listener = new Listener(instanceIdentifier, resourceType, &app); |
85 | 143 | ||
86 | QObject::connect(&app, &QCoreApplication::aboutToQuit, listener, &Listener::closeAllConnections); | 144 | QObject::connect(&app, &QCoreApplication::aboutToQuit, listener, &Listener::closeAllConnections); |
87 | QObject::connect(listener, &Listener::noClients, &app, &QCoreApplication::quit); | 145 | QObject::connect(listener, &Listener::noClients, &app, &QCoreApplication::quit); |