Skip to content

Commit

Permalink
Added checks for scripts stuck in dead loop.
Browse files Browse the repository at this point in the history
  • Loading branch information
MiranDMC committed Dec 2, 2024
1 parent e173c63 commit 510dd73
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 1 deletion.
24 changes: 24 additions & 0 deletions cleo_plugins/DebugUtils/DebugUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "CLEO.h"
#include "CLEO_Utils.h"
#include "ScreenLog.h"
#include "ScriptLog.h"

using namespace CLEO;

Expand All @@ -25,6 +26,11 @@ class DebugUtils
};
static std::deque<PausedScriptInfo> pausedScripts;

static ScriptLog currScript;

// limits for processing after which script is considered hanging
static size_t configLimitCommand;

// breakpoint continue keys
static const int KeyFirst = VK_F5;
static const size_t KeyCount = 8; // F5 to F12
Expand All @@ -43,6 +49,7 @@ class DebugUtils
}

auto config = GetConfigFilename();
configLimitCommand = GetPrivateProfileInt("Limits", "Command", 100000, config.c_str());

// register opcodes
CLEO_RegisterOpcode(0x00C3, Opcode_DebugOn);
Expand All @@ -64,6 +71,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);
}

Expand Down Expand Up @@ -172,6 +180,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)
Expand All @@ -183,6 +193,18 @@ class DebugUtils
return true;
}

static OpcodeResult WINAPI OnScriptOpcodeProcess(CRunningScript* thread, DWORD opcode)
{
currScript.commandCounter++;
if (currScript.commandCounter > configLimitCommand && !IsLegacyScript(thread))
{
SHOW_ERROR("Over %d,%03d commands executed in a single frame by script %s \nTo prevent the game from freezing, CLEO suspended this script.\n\nTo ignore this error, increase 'command' property in %s.ini file and restart the game.", configLimitCommand / 1000, configLimitCommand % 1000, ScriptInfoStr(thread).c_str(), TARGET_NAME);
return thread->Suspend();
}

return OR_NONE;
}

static void WINAPI OnLog(eLogLevel level, const char* msg)
{
screenLog.Add(level, msg);
Expand Down Expand Up @@ -378,6 +400,8 @@ class DebugUtils

ScreenLog DebugUtils::screenLog = {};
std::deque<DebugUtils::PausedScriptInfo> DebugUtils::pausedScripts;
ScriptLog DebugUtils::currScript = {};
size_t DebugUtils::configLimitCommand;
bool DebugUtils::keysReleased = true;
std::map<std::string, std::ofstream> DebugUtils::logFiles;

1 change: 1 addition & 0 deletions cleo_plugins/DebugUtils/DebugUtils.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ xcopy /Y "$(OutDir)$(TargetName).*" "$(GTA_SA_DIR)\cleo\cleo_plugins\"
<ClInclude Include="..\..\cleo_sdk\CLEO.h" />
<ClInclude Include="..\..\cleo_sdk\CLEO_Utils.h" />
<ClInclude Include="ScreenLog.h" />
<ClInclude Include="ScriptLog.h" />
</ItemGroup>
<ItemGroup>
<None Include="SA.DebugUtils.ini" />
Expand Down
1 change: 1 addition & 0 deletions cleo_plugins/DebugUtils/DebugUtils.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<ClInclude Include="..\..\cleo_sdk\CLEO_Utils.h">
<Filter>sdk</Filter>
</ClInclude>
<ClInclude Include="ScriptLog.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="sdk">
Expand Down
4 changes: 4 additions & 0 deletions cleo_plugins/DebugUtils/SA.DebugUtils.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ FontStyle = 1
ColorError = "FF30EEFF"
ColorDebug = "FFEE30FF"
ColorSystem = "DDDDDDFF"

; limits between 'wait' commands in script after which it is considered hanging
[Limits]
command = 100000
13 changes: 13 additions & 0 deletions cleo_plugins/DebugUtils/ScriptLog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
#include "CLEO.h"

struct ScriptLog
{
size_t commandCounter = 0;

void Reset()
{
commandCounter = 0;
}
};

18 changes: 17 additions & 1 deletion examples/Limits_Info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

script_name {name} "lim_info"

// In case the limits adjuster is used, pools can have really big sizes.
// Iterating through all elements can really create a performance hit.
// The proper solution would be to draw stats on every frame from stats saved in variables,
// and update these stats by processing pools only once every few seconds.
const Pool_Size_Cap = 1111 // walk around, just do not parse all contents of bigger pools

int active = false

while true
Expand Down Expand Up @@ -135,12 +141,22 @@ function GET_POOL_INFO(address :int) : int, int

int size = read_memory_with_offset {address} pool {offset} 0x8 {size} 4 // CPool::m_nSize

// for performance reasons do not iterate through all elements of realy big pools
int processSize
if
size < Pool_Size_Cap
then
processSize = size
else
processSize = Pool_Size_Cap
end

// count empty slots
int byteMap = read_memory_with_offset {address} pool {offset} 0x4 {size} 4 // CPool::m_byteMap

int count = 0
int i = 0
while i < size
while i < processSize
int flags = read_memory_with_offset {address} byteMap {offset} i {size} 1 // tPoolObjectFlags
if
not is_local_var_bit_set_const {number} flags {n} 7 // tPoolObjectFlags::bEmpty
Expand Down

0 comments on commit 510dd73

Please sign in to comment.