From e8173b33bee7a0bb9e2b50a71b91639374594b1d Mon Sep 17 00:00:00 2001 From: Miran Date: Mon, 2 Dec 2024 01:04:44 +0100 Subject: [PATCH] Added checks for scripts stuck in dead loop. --- cleo_plugins/DebugUtils/DebugUtils.cpp | 38 +++++++++++++++++++ cleo_plugins/DebugUtils/DebugUtils.vcxproj | 1 + .../DebugUtils/DebugUtils.vcxproj.filters | 1 + cleo_plugins/DebugUtils/SA.DebugUtils.ini | 5 +++ cleo_plugins/DebugUtils/ScriptLog.h | 15 ++++++++ 5 files changed, 60 insertions(+) create mode 100644 cleo_plugins/DebugUtils/ScriptLog.h diff --git a/cleo_plugins/DebugUtils/DebugUtils.cpp b/cleo_plugins/DebugUtils/DebugUtils.cpp index bd999f82..ada72b4f 100644 --- a/cleo_plugins/DebugUtils/DebugUtils.cpp +++ b/cleo_plugins/DebugUtils/DebugUtils.cpp @@ -9,6 +9,7 @@ #include "CLEO.h" #include "CLEO_Utils.h" #include "ScreenLog.h" +#include "ScriptLog.h" using namespace CLEO; @@ -25,6 +26,12 @@ class DebugUtils }; static std::deque pausedScripts; + static ScriptLog currScript; + + // limits for processing after which script is considered hanging + static size_t configLimitCommand; + static size_t configLimitJump; + // breakpoint continue keys static const int KeyFirst = VK_F5; static const size_t KeyCount = 8; // F5 to F12 @@ -43,6 +50,8 @@ class DebugUtils } auto config = GetConfigFilename(); + configLimitCommand = GetPrivateProfileInt("Limits", "Command", 100000, config.c_str()); + configLimitJump = GetPrivateProfileInt("Limits", "Jump", 20000, config.c_str()); // register opcodes CLEO_RegisterOpcode(0x00C3, Opcode_DebugOn); @@ -64,6 +73,7 @@ class DebugUtils CLEO_RegisterCallback(eCallbackId::Log, OnLog); CLEO_RegisterCallback(eCallbackId::DrawingFinished, OnDrawingFinished); CLEO_RegisterCallback(eCallbackId::ScriptProcess, OnScriptProcess); + CLEO_RegisterCallback(eCallbackId::ScriptOpcodeProcess, OnScriptOpcodeProcess); CLEO_RegisterCallback(eCallbackId::ScriptsFinalize, OnScriptsFinalize); } @@ -172,6 +182,8 @@ class DebugUtils static bool WINAPI OnScriptProcess(CScriptThread* thread) { + currScript.Reset(); + for (size_t i = 0; i < pausedScripts.size(); i++) { if (pausedScripts[i].ptr == thread) @@ -183,6 +195,29 @@ class DebugUtils return true; } + static OpcodeResult WINAPI OnScriptOpcodeProcess(CRunningScript* pScript, DWORD opcode) + { + currScript.commandCounter++; + if (currScript.commandCounter > configLimitCommand) + { + SHOW_ERROR("More than %d commands executed in single processing of script %s \nScript considered stuck and was suspended.\n\nTo ignore this error, increase 'command' property in %s.ini file.", configLimitCommand, ScriptInfoStr(pScript).c_str(), TARGET_NAME); + return pScript->Suspend(); + } + + if (opcode == 0x0002 || opcode == 0x004D) // goto, goto_if_false + { + currScript.jumpCounter++; + + if (currScript.jumpCounter > configLimitJump) + { + SHOW_ERROR("More than %d jump commands executed in single processing of script %s \nScript considered stuck and was suspended.\n\nTo ignore this error, increase 'jump' property in %s.ini file.", configLimitJump, ScriptInfoStr(pScript).c_str(), TARGET_NAME); + return pScript->Suspend(); + } + } + + return OR_NONE; + } + static void WINAPI OnLog(eLogLevel level, const char* msg) { screenLog.Add(level, msg); @@ -378,6 +413,9 @@ class DebugUtils ScreenLog DebugUtils::screenLog = {}; std::deque DebugUtils::pausedScripts; +ScriptLog DebugUtils::currScript = {}; +size_t DebugUtils::configLimitCommand; +size_t DebugUtils::configLimitJump; bool DebugUtils::keysReleased = true; std::map DebugUtils::logFiles; diff --git a/cleo_plugins/DebugUtils/DebugUtils.vcxproj b/cleo_plugins/DebugUtils/DebugUtils.vcxproj index 926927ce..7e0c1159 100644 --- a/cleo_plugins/DebugUtils/DebugUtils.vcxproj +++ b/cleo_plugins/DebugUtils/DebugUtils.vcxproj @@ -136,6 +136,7 @@ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\" + diff --git a/cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters b/cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters index 339e6e43..8bcd68a5 100644 --- a/cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters +++ b/cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters @@ -24,6 +24,7 @@ sdk + diff --git a/cleo_plugins/DebugUtils/SA.DebugUtils.ini b/cleo_plugins/DebugUtils/SA.DebugUtils.ini index 03a654fe..8061bb71 100644 --- a/cleo_plugins/DebugUtils/SA.DebugUtils.ini +++ b/cleo_plugins/DebugUtils/SA.DebugUtils.ini @@ -22,3 +22,8 @@ FontStyle = 1 ColorError = "FF30EEFF" ColorDebug = "FFEE30FF" ColorSystem = "DDDDDDFF" + +; limits between 'wait' command in script after which it is considered hanging +[Limits] +command = 100000 +jump = 20000 diff --git a/cleo_plugins/DebugUtils/ScriptLog.h b/cleo_plugins/DebugUtils/ScriptLog.h new file mode 100644 index 00000000..bfeb38c1 --- /dev/null +++ b/cleo_plugins/DebugUtils/ScriptLog.h @@ -0,0 +1,15 @@ +#pragma once +#include "CLEO.h" + +struct ScriptLog +{ + size_t commandCounter = 0; + size_t jumpCounter = 0; + + void Reset() + { + commandCounter = 0; + jumpCounter = 0; + } +}; +