diff --git a/Runtime/CInfiniteLoopDetector.cpp b/Runtime/CInfiniteLoopDetector.cpp new file mode 100644 index 000000000..0d4c2b56c --- /dev/null +++ b/Runtime/CInfiniteLoopDetector.cpp @@ -0,0 +1,37 @@ +#include "Runtime/CInfiniteLoopDetector.hpp" +#include + +namespace metaforce { +namespace { +logvisor::Module Log("CInfiniteLoopDetector"); +std::chrono::system_clock::time_point g_WatchDog = std::chrono::system_clock::now(); +std::mutex g_mutex; +} // namespace + +CInfiniteLoopDetector::CInfiniteLoopDetector(int duration) +: m_duration(duration), m_futureObj(m_stopRequested.get_future()) {} + +bool CInfiniteLoopDetector::stopRequested() const { + return m_futureObj.wait_for(std::chrono::milliseconds(0)) != std::future_status::timeout; +} +void CInfiniteLoopDetector::run() { + std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); + while (!stopRequested()) { + if (std::chrono::duration_cast(std::chrono::system_clock::now() - start) > + std::chrono::milliseconds(m_duration)) { + std::lock_guard guard(g_mutex); + if (std::chrono::duration_cast(std::chrono::system_clock::now() - g_WatchDog) > + std::chrono::milliseconds(m_duration)) { + Log.report(logvisor::Fatal, FMT_STRING("INFINITE LOOP DETECTED!")); + } + } + } +} + +void CInfiniteLoopDetector::UpdateWatchDog(std::chrono::system_clock::time_point time) { + std::lock_guard guard(g_mutex); + g_WatchDog = time; +} + +void CInfiniteLoopDetector::stop() { m_stopRequested.set_value(); } +} // namespace metaforce diff --git a/Runtime/CInfiniteLoopDetector.hpp b/Runtime/CInfiniteLoopDetector.hpp new file mode 100644 index 000000000..92c89e1f0 --- /dev/null +++ b/Runtime/CInfiniteLoopDetector.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +namespace metaforce { +class CInfiniteLoopDetector { + int m_duration = 0; + std::mutex m_mutex; + std::promise m_stopRequested; + std::future m_futureObj; + bool stopRequested() const; +public: + explicit CInfiniteLoopDetector(int duration=1000); + void run(); + void stop(); + static void UpdateWatchDog(std::chrono::system_clock::time_point WatchDog); +}; +} \ No newline at end of file diff --git a/Runtime/CMain.cpp b/Runtime/CMain.cpp index 3be3df737..42f3fadf7 100644 --- a/Runtime/CMain.cpp +++ b/Runtime/CMain.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "Runtime/CInfiniteLoopDetector.hpp" #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN @@ -308,6 +309,10 @@ public: } bool onAppIdle(float realDt) noexcept override { +#ifdef NDEBUG + /* Ping the watchdog to let it know we're still alive */ + CInfiniteLoopDetector::UpdateWatchDog(std::chrono::system_clock::now()); +#endif if (auto* input = g_InputGenerator) { if (!m_deferredControllers.empty()) { for (const auto which : m_deferredControllers) { @@ -605,7 +610,18 @@ int main(int argc, char** argv) { .width = icon.width, .height = icon.height, }; +#ifdef NDEBUG + /* Before we start running the app, lets get a thread going to detect any infinite loops */ + metaforce::CInfiniteLoopDetector infiniteLoopDetector; + std::thread infiniteLoopDetectorThread(&metaforce::CInfiniteLoopDetector::run, &infiniteLoopDetector); + infiniteLoopDetectorThread.detach(); aurora::app_run(std::move(app), std::move(data), argc, argv); + infiniteLoopDetector.stop(); +#else + /* Debuggers can interrupt the loop detector and make it unable to perform its job correctly, so lets not detect + * infinite loops in a debug build */ + aurora::app_run(std::move(app), std::move(data), argc, argv); +#endif return 0; } #endif diff --git a/Runtime/CMakeLists.txt b/Runtime/CMakeLists.txt index 6a67e9e7d..048fbd34c 100644 --- a/Runtime/CMakeLists.txt +++ b/Runtime/CMakeLists.txt @@ -61,6 +61,7 @@ set(RUNTIME_SOURCES_B ${PARTICLE_SOURCES} ${WORLD_SOURCES} ${WEAPON_SOURCES} + CInfiniteLoopDetector.hpp CInfiniteLoopDetector.cpp ConsoleVariables/FileStoreManager.hpp ConsoleVariables/FileStoreManager.cpp ConsoleVariables/CVar.hpp ConsoleVariables/CVar.cpp ConsoleVariables/CVarManager.hpp ConsoleVariables/CVarManager.cpp diff --git a/aurora/lib/aurora.cpp b/aurora/lib/aurora.cpp index 6df00721b..8a1192bee 100644 --- a/aurora/lib/aurora.cpp +++ b/aurora/lib/aurora.cpp @@ -138,9 +138,15 @@ static bool poll_events() noexcept { break; } case SDL_CONTROLLERAXISMOTION: { - g_AppDelegate->onControllerAxis( - event.caxis.which, input::translate_controller_axis(static_cast(event.caxis.axis)), - event.caxis.value); + if (event.caxis.value > 8000 || event.caxis.value < -8000) { + g_AppDelegate->onControllerAxis( + event.caxis.which, input::translate_controller_axis(static_cast(event.caxis.axis)), + event.caxis.value); + } else { + g_AppDelegate->onControllerAxis( + event.caxis.which, input::translate_controller_axis(static_cast(event.caxis.axis)), + 0); + } break; } case SDL_KEYDOWN: {