History

Add a watchdog thread to trigger a crash on detecting a deadlock

Brad Davis committed 10 years ago

Commit 95f5d821 parent d1401794 files · +52 −0Browse files

Showing the changes to interface/src/Application.cpp (1 of 4 files). Show all

Unified · Split

interface/src/Application.cpp+48−0
@@ -235,6 +235,42 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi · 234 unmodified lines
235 { AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl }235 { AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl }
236};236};
237 237
238class DeadlockWatchdogThread : public QThread {
239public:
240 static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1;
241 static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
242 static const unsigned long MAX_HEARTBEAT_AGE_USECS = 10 * USECS_PER_SECOND;
243
244 // Set the heartbeat on launch
245 DeadlockWatchdogThread() {
246 QTimer* heartbeatTimer = new QTimer();
247 connect(heartbeatTimer, &QTimer::timeout, [this] {
248 _heartbeat = usecTimestampNow();
249 });
250 heartbeatTimer->start(HEARTBEAT_UPDATE_INTERVAL_SECS * MSECS_PER_SECOND);
251 }
252
253 void deadlockDetectionCrash() {
254 uint32_t* crashTrigger = nullptr;
255 *crashTrigger = 0xDEAD10CC;
256 }
257
258 void run() override {
259 while (!qApp->isAboutToQuit()) {
260 QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS);
261 auto now = usecTimestampNow();
262 auto lastHeartbeatAge = now - _heartbeat;
263 if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
264 deadlockDetectionCrash();
265 }
266 }
267 }
268
269 static std::atomic<uint64_t> _heartbeat;
270};
271
272std::atomic<uint64_t> DeadlockWatchdogThread::_heartbeat;
273
238#ifdef Q_OS_WIN274#ifdef Q_OS_WIN
239class MyNativeEventFilter : public QAbstractNativeEventFilter {275class MyNativeEventFilter : public QAbstractNativeEventFilter {
240public:276public:
@@ -457,6 +493,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 216 unmodified lines
457 493
458 auto nodeList = DependencyManager::get<NodeList>();494 auto nodeList = DependencyManager::get<NodeList>();
459 495
496 // Set up a watchdog thread to intentionally crash the application on deadlocks
497 (new DeadlockWatchdogThread())->start();
498
460 qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion());499 qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
461 500
462 _bookmarks = new Bookmarks(); // Before setting up the menu501 _bookmarks = new Bookmarks(); // Before setting up the menu
@@ -4960,6 +4999,15 @@ void Application::crashApplication() { · 4497 unmodified lines
4960 Q_UNUSED(value);4999 Q_UNUSED(value);
4961}5000}
4962 5001
5002void Application::deadlockApplication() {
5003 qCDebug(interfaceapp) << "Intentionally deadlocked Interface";
5004 // Using a loop that will *technically* eventually exit (in ~600 billion years)
5005 // to avoid compiler warnings about a loop that will never exit
5006 for (uint64_t i = 1; i != 0; ++i) {
5007 QThread::sleep(1);
5008 }
5009}
5010
4963void Application::setActiveDisplayPlugin(const QString& pluginName) {5011void Application::setActiveDisplayPlugin(const QString& pluginName) {
4964 auto menu = Menu::getInstance();5012 auto menu = Menu::getInstance();
4965 foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {5013 foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {