mirror of https://github.com/AxioDL/metaforce.git
Add CInfiniteLoopDetector to detect infinite loops in release builds
This commit is contained in:
parent
740114af9e
commit
d93cf46bc3
|
@ -0,0 +1,37 @@
|
|||
#include "Runtime/CInfiniteLoopDetector.hpp"
|
||||
#include <logvisor/logvisor.hpp>
|
||||
|
||||
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::milliseconds>(std::chrono::system_clock::now() - start) >
|
||||
std::chrono::milliseconds(m_duration)) {
|
||||
std::lock_guard<std::mutex> guard(g_mutex);
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(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<std::mutex> guard(g_mutex);
|
||||
g_WatchDog = time;
|
||||
}
|
||||
|
||||
void CInfiniteLoopDetector::stop() { m_stopRequested.set_value(); }
|
||||
} // namespace metaforce
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <future>
|
||||
|
||||
namespace metaforce {
|
||||
class CInfiniteLoopDetector {
|
||||
int m_duration = 0;
|
||||
std::mutex m_mutex;
|
||||
std::promise<void> m_stopRequested;
|
||||
std::future<void> 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);
|
||||
};
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
#include <string_view>
|
||||
#include <numeric>
|
||||
#include <iostream>
|
||||
#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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -138,9 +138,15 @@ static bool poll_events() noexcept {
|
|||
break;
|
||||
}
|
||||
case SDL_CONTROLLERAXISMOTION: {
|
||||
if (event.caxis.value > 8000 || event.caxis.value < -8000) {
|
||||
g_AppDelegate->onControllerAxis(
|
||||
event.caxis.which, input::translate_controller_axis(static_cast<SDL_GameControllerAxis>(event.caxis.axis)),
|
||||
event.caxis.value);
|
||||
} else {
|
||||
g_AppDelegate->onControllerAxis(
|
||||
event.caxis.which, input::translate_controller_axis(static_cast<SDL_GameControllerAxis>(event.caxis.axis)),
|
||||
0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_KEYDOWN: {
|
||||
|
|
Loading…
Reference in New Issue