Skip to content

Commit

Permalink
Merge Better Lua error handling (pr-2631)
Browse files Browse the repository at this point in the history
4a53580 - tweak(scripting/lua): call __tostring metamethod on errors
a2c7365 - fix(scripting/lua): format error messages
  • Loading branch information
prikolium-cfx committed Aug 20, 2024
2 parents 58bed26 + 4a53580 commit 918265a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 26 deletions.
57 changes: 32 additions & 25 deletions code/components/citizen-scripting-lua/src/LuaScriptRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,16 @@ static constexpr std::pair<const char*, ManifestVersion> g_scriptVersionPairs[]

// Utility for sanitizing error messages in an unprotected states. Avoid string coercion (cvt2str) to ensure errors
// do not compound.
#define LUA_SCRIPT_TRACE(L, MSG, ...) \
try \
{ \
const char* err = "error object is not a string"; \
if (lua_type((L), -1) == LUA_TSTRING) \
{ \
err = lua_tostring((L), -1); \
} \
ScriptTrace(MSG ": %s\n", ##__VA_ARGS__, err); \
} \
catch (...) \
{ \
} \
lua_pop((L), 1)
#define LUA_SCRIPT_TRACE(L, MSG, ...) \
try \
{ \
const char* err = Lua_GetErrorMessage(L, -1); \
ScriptTrace(MSG ": %s\n", ##__VA_ARGS__, err); \
} \
catch (...) \
{ \
} \
lua_pop((L), 1)

/// <summary>
/// </summary>
Expand Down Expand Up @@ -218,6 +214,26 @@ static int Lua_Print(lua_State* L)
return 0;
}

static const char* Lua_GetErrorMessage(lua_State* L, int index)
{
const char* msg = "error object is not a string";
if (lua_type(L, index) == LUA_TSTRING)
{
msg = lua_tostring(L, index);
}
else if (luaL_callmeta(L, index, "__tostring") && lua_type(L, -1) == LUA_TSTRING)
{
msg = lua_tostring(L, -1);
lua_pop(L, 1);
}
else
{
lua_pop(L, 1);
}

return msg;
}

#if LUA_VERSION_NUM >= 504
static void Lua_Warn(void* ud, const char* msg, int tocont)
{
Expand Down Expand Up @@ -970,12 +986,7 @@ bool LuaScriptRuntime::RunBookmark(uint64_t bookmark)
{
if (resumeValue != LUA_OK)
{
std::string err = "error object is not a string";
if (lua_type(thread, -1) == LUA_TSTRING)
{
err = lua_tostring(thread, -1);
}

std::string err = Lua_GetErrorMessage(thread, -1);
static auto formatStackTrace = fx::ScriptEngine::GetNativeHandler(HashString("FORMAT_STACK_TRACE"));
std::string stackData = "(nil stack trace)";

Expand All @@ -997,11 +1008,7 @@ bool LuaScriptRuntime::RunBookmark(uint64_t bookmark)
#if LUA_VERSION_NUM >= 504
int resetStatus = lua_resetthread(thread);

std::string resetErr = "error object is not a string";
if (lua_type(thread, -1) == LUA_TSTRING)
{
resetErr = lua_tostring(thread, -1);
}
std::string resetErr = Lua_GetErrorMessage(thread, -1);

// We can't just check whether the resetStatus is OK because
// if there was no error lua_resetthread returns the same status it received
Expand Down
2 changes: 1 addition & 1 deletion data/shared/citizen/scripting/lua/scheduler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ local function doStackFormat(err)
return nil
end

return '^1SCRIPT ERROR: ' .. err .. "^7\n" .. fst
return string.format('^1SCRIPT ERROR: %s^7\n%s', err or '', fst)
end

Citizen.SetCallRefRoutine(function(refId, argsSerialized)
Expand Down

0 comments on commit 918265a

Please sign in to comment.