From 0c1277ae7a21bbe58cfede88ff3349e06762e965 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 12 Apr 2016 16:44:11 -0700 Subject: [PATCH 1/8] Add CrashHelpers.h and add to separate submenu --- interface/src/Menu.cpp | 27 ++++++++-- interface/src/Menu.h | 8 ++- libraries/shared/src/CrashHelpers.h | 80 +++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 libraries/shared/src/CrashHelpers.h diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f6386ba72d..ae1aa3381e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -582,12 +583,30 @@ Menu::Menu() { } addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls); + MenuWrapper* crashMenu = developerMenu->addMenu("Crash"); + // Developer > Display Crash Options addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true); - // Developer > Crash Application - addActionToQMenuAndActionHash(developerMenu, MenuOption::CrashInterface, 0, qApp, SLOT(crashApplication())); - // Developer > Deadlock Application - addActionToQMenuAndActionHash(developerMenu, MenuOption::DeadlockInterface, 0, qApp, SLOT(deadlockApplication())); + + addActionToQMenuAndActionHash(crashMenu, MenuOption::DeadlockInterface, 0, qApp, SLOT(deadlockApplication())); + + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashPureVirtualFunction); + connect(action, &QAction::triggered, qApp, []() { crash::pureVirtualCall(); }); + + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashDoubleFree); + connect(action, &QAction::triggered, qApp, []() { crash::doubleFree(); }); + + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashAbort); + connect(action, &QAction::triggered, qApp, []() { crash::doAbort(); }); + + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNullDereference); + connect(action, &QAction::triggered, qApp, []() { crash::nullDeref(); }); + + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashOutOfBoundsVectorAccess); + connect(action, &QAction::triggered, qApp, []() { crash::outOfBoundsVectorCrash(); }); + + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFault); + connect(action, &QAction::triggered, qApp, []() { crash::newFault(); }); // Developer > Log... addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 48bda01076..80dc8750fb 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -65,7 +65,13 @@ namespace MenuOption { const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; const QString CoupleEyelids = "Couple Eyelids"; - const QString CrashInterface = "Crash Interface"; +// const QString CrashInterface = "Crash Interface"; + const QString CrashPureVirtualFunction = "Pure Virtual Function Call"; + const QString CrashDoubleFree = "Double Free"; + const QString CrashNullDereference = "Null Dereference"; + const QString CrashAbort = "Abort"; + const QString CrashOutOfBoundsVectorAccess = "Out of Bounds Vector Access"; + const QString CrashNewFault = "New Fault"; const QString DeadlockInterface = "Deadlock Interface"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; diff --git a/libraries/shared/src/CrashHelpers.h b/libraries/shared/src/CrashHelpers.h new file mode 100644 index 0000000000..9146df746c --- /dev/null +++ b/libraries/shared/src/CrashHelpers.h @@ -0,0 +1,80 @@ +// +// CrashHelpers.h +// libraries/shared/src +// +// Created by Ryan Huffman on 11 April 2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once + +#ifndef hifi_CrashHelpers_h +#define hifi_CrashHelpers_h + +namespace crash { + +class B; +class A { +public: + A(B* b) : _b(b) { } + ~A(); + virtual void virtualFunction() = 0; + +private: + B* _b; +}; + +class B : public A { +public: + B() : A(this) { } + virtual void virtualFunction() { } +}; + +A::~A() { + _b->virtualFunction(); +} + +void pureVirtualCall() { + + qDebug() << "About to make a pure virtual call"; + { + B b; + } +} + +void doubleFree() { + qDebug() << "About to double delete memory"; + int* blah = new int(200); + delete blah; + delete blah; +} + +void nullDeref() { + qDebug() << "About to dereference a null pointer"; + int* p = nullptr; + *p = 1; +} + +void doAbort() { + qDebug() << "About to abort"; + abort(); +} + +void outOfBoundsVectorCrash() { + qDebug() << "std::vector out of bounds crash!"; + std::vector v; + v[0] = 42; +} + +void newFault() { + qDebug() << "About to crash inside new fault"; + // Force crash with large allocation + int *crash = new int[std::numeric_limits::max()]; +} + +} + +#endif // hifi_CrashHelpers_h From 91da4229ace5f76a9887f2345aff9e9e0d53a1c5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 13 Apr 2016 09:42:20 -0700 Subject: [PATCH 2/8] Fix unused variable warning in CrashHelpers.h --- libraries/shared/src/CrashHelpers.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/CrashHelpers.h b/libraries/shared/src/CrashHelpers.h index 9146df746c..1f5893b3b4 100644 --- a/libraries/shared/src/CrashHelpers.h +++ b/libraries/shared/src/CrashHelpers.h @@ -72,9 +72,9 @@ void outOfBoundsVectorCrash() { void newFault() { qDebug() << "About to crash inside new fault"; // Force crash with large allocation - int *crash = new int[std::numeric_limits::max()]; -} - + int* crash = new int[std::numeric_limits::max()]; + // Use variable to suppress warning + crash[0] = 0; } #endif // hifi_CrashHelpers_h From 7fbaa77c0b027e18cd34a63c6ca82ec11fca6072 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 13 Apr 2016 10:24:14 -0700 Subject: [PATCH 3/8] Fix missing brace in namespace --- libraries/shared/src/CrashHelpers.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/CrashHelpers.h b/libraries/shared/src/CrashHelpers.h index 1f5893b3b4..348926d19a 100644 --- a/libraries/shared/src/CrashHelpers.h +++ b/libraries/shared/src/CrashHelpers.h @@ -72,9 +72,11 @@ void outOfBoundsVectorCrash() { void newFault() { qDebug() << "About to crash inside new fault"; // Force crash with large allocation - int* crash = new int[std::numeric_limits::max()]; + int* data = new int[std::numeric_limits::max()]; // Use variable to suppress warning - crash[0] = 0; + data[0] = 0; +} + } #endif // hifi_CrashHelpers_h From fa49c213cc59ed4cafc7bbed1d9a305b758b3055 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 13 Apr 2016 10:24:56 -0700 Subject: [PATCH 4/8] Add threaded crashes --- interface/src/Menu.cpp | 14 ++++++++++++++ interface/src/Menu.h | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ae1aa3381e..0d5b304c93 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -13,6 +13,8 @@ #include #include +#include + #include #include #include @@ -592,21 +594,33 @@ Menu::Menu() { action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashPureVirtualFunction); connect(action, &QAction::triggered, qApp, []() { crash::pureVirtualCall(); }); + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashPureVirtualFunctionThreaded); + connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::pureVirtualCall(); }); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashDoubleFree); connect(action, &QAction::triggered, qApp, []() { crash::doubleFree(); }); + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashDoubleFreeThreaded); + connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::doubleFree(); }); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashAbort); connect(action, &QAction::triggered, qApp, []() { crash::doAbort(); }); + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashAbortThreaded); + connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::doAbort(); }); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNullDereference); connect(action, &QAction::triggered, qApp, []() { crash::nullDeref(); }); + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNullDereferenceThreaded); + connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::nullDeref(); }); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashOutOfBoundsVectorAccess); connect(action, &QAction::triggered, qApp, []() { crash::outOfBoundsVectorCrash(); }); + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashOutOfBoundsVectorAccessThreaded); + connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::outOfBoundsVectorCrash(); }); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFault); connect(action, &QAction::triggered, qApp, []() { crash::newFault(); }); + action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFaultThreaded); + connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::newFault(); }); }); // Developer > Log... addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 80dc8750fb..5a27a328b5 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -65,13 +65,18 @@ namespace MenuOption { const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; const QString CoupleEyelids = "Couple Eyelids"; -// const QString CrashInterface = "Crash Interface"; const QString CrashPureVirtualFunction = "Pure Virtual Function Call"; + const QString CrashPureVirtualFunctionThreaded = "Pure Virtual Function Call (threaded)"; const QString CrashDoubleFree = "Double Free"; + const QString CrashDoubleFreeThreaded = "Double Free (threaded)"; const QString CrashNullDereference = "Null Dereference"; + const QString CrashNullDereferenceThreaded = "Null Dereference (threaded)"; const QString CrashAbort = "Abort"; + const QString CrashAbortThreaded = "Abort (threaded)"; const QString CrashOutOfBoundsVectorAccess = "Out of Bounds Vector Access"; + const QString CrashOutOfBoundsVectorAccessThreaded = "Out of Bounds Vector Access (threaded)"; const QString CrashNewFault = "New Fault"; + const QString CrashNewFaultThreaded = "New Fault (threaded)"; const QString DeadlockInterface = "Deadlock Interface"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; From 6cbd31fa518873d5136d9b8ef484341c5da2e903 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 13 Apr 2016 11:28:37 -0700 Subject: [PATCH 5/8] Cleanup unnecessary scoping in pureVirtualCall --- libraries/shared/src/CrashHelpers.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/shared/src/CrashHelpers.h b/libraries/shared/src/CrashHelpers.h index 348926d19a..ba3f7b6e30 100644 --- a/libraries/shared/src/CrashHelpers.h +++ b/libraries/shared/src/CrashHelpers.h @@ -38,11 +38,8 @@ A::~A() { } void pureVirtualCall() { - qDebug() << "About to make a pure virtual call"; - { - B b; - } + B b; } void doubleFree() { From e563de9ef8f1d16532df238fea3a36431f7984f2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 13 Apr 2016 11:28:54 -0700 Subject: [PATCH 6/8] Fix 'array is too large' warning --- libraries/shared/src/CrashHelpers.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/shared/src/CrashHelpers.h b/libraries/shared/src/CrashHelpers.h index ba3f7b6e30..0ea927df75 100644 --- a/libraries/shared/src/CrashHelpers.h +++ b/libraries/shared/src/CrashHelpers.h @@ -68,8 +68,15 @@ void outOfBoundsVectorCrash() { void newFault() { qDebug() << "About to crash inside new fault"; + + // Disable "array is too large" warning for clang. We are deliberately + // choosing a large number so that we will crash! +#pragma clang diagnostic push +#pragma clang diagnostic ignore "-Wbad-array-new-length" // Force crash with large allocation int* data = new int[std::numeric_limits::max()]; +#pragma clang diagnostic pop + // Use variable to suppress warning data[0] = 0; } From 9ee81a73c704a321d3b2d53ae86a112de36ec123 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 13 Apr 2016 13:41:45 -0700 Subject: [PATCH 7/8] Fix clang warning in CrashHelpers::newFault --- libraries/shared/src/CrashHelpers.h | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libraries/shared/src/CrashHelpers.h b/libraries/shared/src/CrashHelpers.h index 0ea927df75..dae39d4a99 100644 --- a/libraries/shared/src/CrashHelpers.h +++ b/libraries/shared/src/CrashHelpers.h @@ -69,16 +69,12 @@ void outOfBoundsVectorCrash() { void newFault() { qDebug() << "About to crash inside new fault"; - // Disable "array is too large" warning for clang. We are deliberately - // choosing a large number so that we will crash! -#pragma clang diagnostic push -#pragma clang diagnostic ignore "-Wbad-array-new-length" - // Force crash with large allocation - int* data = new int[std::numeric_limits::max()]; -#pragma clang diagnostic pop + // Force crash with multiple large allocations + while (true) { + const size_t GIGABYTE = 1024 * 1024 * 1024; + new char[GIGABYTE]; + } - // Use variable to suppress warning - data[0] = 0; } } From bc247ec0580fc083152051c115cdaf9255ab4c89 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 13 Apr 2016 14:01:41 -0700 Subject: [PATCH 8/8] Remove unused Application::crashApplication() --- interface/src/Application.cpp | 7 ------- interface/src/Application.h | 1 - 2 files changed, 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a6555352dd..d254218180 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5176,13 +5176,6 @@ mat4 Application::getHMDSensorPose() const { return mat4(); } -void Application::crashApplication() { - qCDebug(interfaceapp) << "Intentionally crashed Interface"; - QObject* object = nullptr; - bool value = object->isWindowType(); - Q_UNUSED(value); -} - void Application::deadlockApplication() { qCDebug(interfaceapp) << "Intentionally deadlocked Interface"; // Using a loop that will *technically* eventually exit (in ~600 billion years) diff --git a/interface/src/Application.h b/interface/src/Application.h index ebe2e53584..f15d8dfb98 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -276,7 +276,6 @@ public slots: void updateHeartbeat() const; - static void crashApplication(); static void deadlockApplication(); void rotationModeChanged() const;