Skip to content

Commit e0c55db

Browse files
committed
Refactor Lua error output
This commit revisits bc0e083, 4958e2f, 1ca95df and a84c61a Fixes #1799
1 parent ac4ba75 commit e0c55db

File tree

2 files changed

+91
-117
lines changed

2 files changed

+91
-117
lines changed

src/xrScriptEngine/script_engine.cpp

+84-110
Original file line numberDiff line numberDiff line change
@@ -144,33 +144,43 @@ void CScriptEngine::reinit()
144144

145145
void CScriptEngine::print_stack(lua_State* L)
146146
{
147-
if (!m_stack_is_ready || logReenterability)
148-
return;
149-
150-
logReenterability = true;
151-
m_stack_is_ready = false;
152-
153147
if (L == nullptr)
154148
L = lua();
155149

156-
if (strstr(Core.Params, "-luadumpstate"))
150+
static bool dump = strstr(Core.Params, "-luadumpstate");
151+
152+
if (lua_isstring(L, -1))
157153
{
158-
Log("\nSCRIPT ERROR");
159-
lua_Debug l_tDebugInfo;
160-
for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); i++)
154+
pcstr err = lua_tostring(L, -1);
155+
script_log(LuaMessageType::Error, "%s", err);
156+
}
157+
158+
lua_Debug l_tDebugInfo;
159+
for (int i = 0; lua_getstack(L, i, &l_tDebugInfo); i++)
160+
{
161+
lua_getinfo(L, "nSlu", &l_tDebugInfo);
162+
163+
if (!xr_strcmp(l_tDebugInfo.what, "C"))
161164
{
162-
lua_getinfo(L, "nSlu", &l_tDebugInfo);
163-
if (!l_tDebugInfo.name)
164-
Msg("%2d : [%s] %s(%d)", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline);
165-
else if (!xr_strcmp(l_tDebugInfo.what, "C"))
166-
Msg("%2d : [C ] %s", i, l_tDebugInfo.name);
165+
script_log(LuaMessageType::Error, "%2d : [C ] %s", i, l_tDebugInfo.name ? l_tDebugInfo.name : "");
166+
}
167+
else
168+
{
169+
string_path temp;
170+
if (l_tDebugInfo.name)
171+
xr_sprintf(temp, "%s(%d)", l_tDebugInfo.name, l_tDebugInfo.linedefined);
167172
else
168-
{
169-
Msg("%2d : [%s] %s(%d) : %s", i, l_tDebugInfo.what, l_tDebugInfo.short_src, l_tDebugInfo.currentline,
170-
l_tDebugInfo.name);
171-
}
173+
xr_sprintf(temp, "function <%s:%d>", l_tDebugInfo.short_src, l_tDebugInfo.linedefined);
174+
175+
script_log(LuaMessageType::Error, "%2d : [%3s] %s(%d) : %s", i, l_tDebugInfo.what,
176+
l_tDebugInfo.short_src, l_tDebugInfo.currentline, temp);
177+
}
178+
179+
// Giperion: verbose log
180+
if (dump)
181+
{
182+
const auto top = lua_gettop(L);
172183

173-
// Giperion: verbose log
174184
Log("\nLua state dump:\n\tLocals: ");
175185
pcstr name = nullptr;
176186
int VarID = 1;
@@ -188,19 +198,11 @@ void CScriptEngine::print_stack(lua_State* L)
188198
Log("Can't dump lua state - Engine corrupted");
189199
}
190200
Log("End of Lua state dump.\n");
191-
// -Giperion
201+
202+
luabind::detail::stack_pop{ L, lua_gettop(L) - top }; // restore lua stack
192203
}
204+
// -Giperion
193205
}
194-
else
195-
{
196-
luaL_traceback(L, L, nullptr, 1); // add lua traceback to it
197-
pcstr sErrorText = lua_tostring(L, -1); // get combined error text from lua stack
198-
Log(sErrorText);
199-
lua_pop(L, 1); // restore lua stack
200-
}
201-
202-
m_stack_is_ready = true;
203-
logReenterability = false;
204206
}
205207

206208
void CScriptEngine::LogTable(lua_State* luaState, pcstr S, int level)
@@ -372,7 +374,8 @@ lua_State* L, LPCSTR caBuffer, size_t tSize, LPCSTR caScriptName, LPCSTR caNameS
372374
l_iErrorCode = luaL_loadbuffer(L, caBuffer, tSize, caScriptName);
373375
if (l_iErrorCode)
374376
{
375-
onErrorCallback(L, caScriptName, l_iErrorCode);
377+
print_output(L, caScriptName, l_iErrorCode);
378+
on_error(L);
376379
return false;
377380
}
378381
return true;
@@ -424,7 +427,9 @@ bool CScriptEngine::do_file(LPCSTR caScriptName, LPCSTR caNameSpaceName)
424427
#endif
425428
if (l_iErrorCode)
426429
{
427-
onErrorCallback(lua(), caScriptName, l_iErrorCode);
430+
print_output(lua(), caScriptName, l_iErrorCode);
431+
on_error(lua());
432+
lua_settop(lua(), start);
428433
return false;
429434
}
430435
return true;
@@ -554,53 +559,25 @@ luabind::object CScriptEngine::name_space(LPCSTR namespace_name)
554559
}
555560
}
556561

557-
struct raii_guard : private Noncopyable
562+
bool CScriptEngine::print_output(lua_State* L, pcstr caScriptFileName, int errorCode, pcstr caErrorText)
558563
{
559-
CScriptEngine* m_script_engine;
560-
int m_error_code;
561-
const char*& m_error_description;
562-
563-
raii_guard(CScriptEngine* scriptEngine, int error_code, const char*& error_description)
564-
: m_script_engine(scriptEngine), m_error_code(error_code), m_error_description(error_description)
565-
{}
564+
CScriptEngine* scriptEngine = GetInstance(L);
565+
VERIFY(scriptEngine);
566566

567-
~raii_guard()
567+
if (caErrorText)
568568
{
569-
#if defined(USE_DEBUGGER) && defined(USE_LUA_STUDIO)
570-
const bool lua_studio_connected = !!m_script_engine->debugger();
571-
if (!lua_studio_connected)
572-
#endif
573-
{
574-
#ifdef DEBUG
575-
static const bool break_on_assert = !!strstr(Core.Params, "-break_on_assert");
576-
#else
577-
static const bool break_on_assert = true; // xxx: there is no point to set it true\false in Release, since
578-
// game will crash anyway in most cases due to XRAY_EXCEPTIONS
579-
// disabled in Release build.
580-
#endif
581-
if (!m_error_code)
582-
return; // Check "lua_pcall_failed" before changing this!
583-
584-
if (break_on_assert)
585-
R_ASSERT2(!m_error_code, m_error_description);
586-
else
587-
Msg("! SCRIPT ERROR: %s", m_error_description);
588-
}
569+
const auto [logHeader, luaLogHeader] = get_message_headers(LuaMessageType::Error);
570+
Msg("%sSCRIPT ERROR: %s\n", logHeader, caErrorText);
589571
}
590-
};
591572

592-
bool CScriptEngine::print_output(lua_State* L, pcstr caScriptFileName, int errorCode, pcstr caErrorText)
593-
{
594-
CScriptEngine* scriptEngine = GetInstance(L);
595-
VERIFY(scriptEngine);
596573
if (errorCode)
597574
print_error(L, errorCode);
598-
scriptEngine->print_stack(L);
599-
pcstr S = "see call_stack for details!";
600-
raii_guard guard(scriptEngine, errorCode, caErrorText ? caErrorText : S);
575+
601576
if (!lua_isstring(L, -1))
602577
return false;
603-
S = lua_tostring(L, -1);
578+
579+
const auto S = lua_tostring(L, -1);
580+
604581
if (!xr_strcmp(S, "cannot resume dead coroutine"))
605582
{
606583
VERIFY2("Please do not return any values from main!!!", caScriptFileName);
@@ -616,7 +593,6 @@ bool CScriptEngine::print_output(lua_State* L, pcstr caScriptFileName, int error
616593
{
617594
if (!errorCode)
618595
scriptEngine->script_log(LuaMessageType::Info, "Output from %s", caScriptFileName);
619-
// scriptEngine->script_log(errorCode ? LuaMessageType::Error : LuaMessageType::Message, "%s", S);
620596
#if defined(USE_DEBUGGER) && !defined(USE_LUA_STUDIO)
621597
if (debugger() && debugger()->Active())
622598
{
@@ -625,34 +601,34 @@ bool CScriptEngine::print_output(lua_State* L, pcstr caScriptFileName, int error
625601
}
626602
#endif
627603
}
628-
if (caErrorText)
629-
S = caErrorText;
604+
630605
return true;
631606
}
632607

633608
void CScriptEngine::print_error(lua_State* L, int iErrorCode)
634609
{
635-
VERIFY(GetInstance(L));
610+
CScriptEngine* scriptEngine = GetInstance(L);
611+
VERIFY(scriptEngine);
636612

637613
switch (iErrorCode)
638614
{
639615
case LUA_ERRRUN:
640-
Log("\n\nSCRIPT RUNTIME ERROR");
616+
scriptEngine->script_log(LuaMessageType::Error, "SCRIPT RUNTIME ERROR");
641617
break;
642618
case LUA_ERRMEM:
643-
Log("\n\nSCRIPT ERROR (memory allocation)");
619+
scriptEngine->script_log(LuaMessageType::Error, "SCRIPT ERROR (memory allocation)");
644620
break;
645621
case LUA_ERRERR:
646-
Log("\n\nSCRIPT ERROR (while running the error handler function)");
622+
scriptEngine->script_log(LuaMessageType::Error, "SCRIPT ERROR (while running the error handler function)");
647623
break;
648624
case LUA_ERRFILE:
649-
Log("\n\nSCRIPT ERROR (while running file)");
625+
scriptEngine->script_log(LuaMessageType::Error, "SCRIPT ERROR (while running file)");
650626
break;
651627
case LUA_ERRSYNTAX:
652-
Log("\n\nSCRIPT SYNTAX ERROR");
628+
scriptEngine->script_log(LuaMessageType::Error, "SCRIPT SYNTAX ERROR");
653629
break;
654630
case LUA_YIELD:
655-
Log("\n\nThread is yielded");
631+
scriptEngine->script_log(LuaMessageType::Info, "Thread is yielded");
656632
break;
657633
default: NODEFAULT;
658634
}
@@ -762,7 +738,6 @@ CScriptEngine::CScriptEngine(bool is_editor, bool is_with_profiler)
762738
luabind::allocator = &luabind_allocator;
763739
luabind::allocator_context = nullptr;
764740
m_current_thread = nullptr;
765-
m_stack_is_ready = false;
766741
m_virtual_machine = nullptr;
767742
m_profiler = is_with_profiler && !is_editor ? xr_new<CScriptProfiler>(this) : nullptr;
768743
m_stack_level = 0;
@@ -817,50 +792,53 @@ void CScriptEngine::unload()
817792
*m_last_no_file = 0;
818793
}
819794

820-
bool CScriptEngine::onErrorCallback(lua_State* L, pcstr scriptName, int errorCode, pcstr err)
821-
{
822-
print_output(L, scriptName, errorCode, err);
823-
on_error(L);
824-
825-
bool ignoreAlways;
826-
const auto result = xrDebug::Fail(ignoreAlways, DEBUG_INFO, "LUA error", err);
827-
828-
return result == AssertionResult::ignore;
829-
}
830-
831795
int CScriptEngine::lua_panic(lua_State* L)
832796
{
833-
onErrorCallback(L, "", LUA_ERRRUN, "PANIC");
797+
print_output(L, "", LUA_ERRRUN, "PANIC");
798+
FATAL("Lua panic");
834799
return 0;
835800
}
836801

837802
void CScriptEngine::lua_error(lua_State* L)
838803
{
839-
pcstr err = lua_tostring(L, -1);
840-
onErrorCallback(L, "", LUA_ERRRUN, err);
804+
print_output(L, "", LUA_ERRRUN);
805+
on_error(L);
806+
807+
#if !XRAY_EXCEPTIONS
808+
xrDebug::Fatal(DEBUG_INFO, "LUA error: %s", lua_tostring(L, -1));
809+
#else
810+
throw lua_tostring(L, -1);
811+
#endif
841812
}
842813

843814
int CScriptEngine::lua_pcall_failed(lua_State* L)
844815
{
845-
const bool isString = lua_isstring(L, -1);
846-
const pcstr err = isString ? lua_tostring(L, -1) : "";
816+
print_output(L, "", LUA_ERRRUN);
817+
on_error(L);
847818

848-
const bool result = onErrorCallback(L, "", LUA_ERRRUN, err);
819+
luabind::detail::stack_pop pop{ L, lua_isstring(L, -1) ? 1 : 0 };
820+
821+
if (xrDebug::WouldShowErrorMessage())
822+
{
823+
const auto err = lua_tostring(L, -1);
849824

850-
if (isString)
851-
lua_pop(L, 1);
825+
static bool ignoreAlways;
826+
const auto result = xrDebug::Fail(ignoreAlways, DEBUG_INFO, "LUA error", err);
852827

853-
if (result)
854-
return LUA_OK;
828+
if (result == AssertionResult::tryAgain || result == AssertionResult::ignore)
829+
return LUA_OK;
830+
}
855831

856832
return LUA_ERRRUN;
857833
}
858-
#if 1 //!XRAY_EXCEPTIONS
834+
835+
#if !XRAY_EXCEPTIONS
859836
void CScriptEngine::lua_cast_failed(lua_State* L, const luabind::type_id& info)
860837
{
861838
string128 buf;
862-
xr_sprintf(buf, "LUA error: cannot cast lua value to %s", info.name());
863-
onErrorCallback(L, "", LUA_ERRRUN, buf);
839+
xr_sprintf(buf, "cannot cast lua value to %s", info.name());
840+
print_output(L, "", LUA_ERRRUN, buf);
841+
xrDebug::Fatal(DEBUG_INFO, "LUA error: cannot cast lua value to %s", info.name());
864842
}
865843
#endif
866844

@@ -898,8 +876,6 @@ void CScriptEngine::lua_hook_call(lua_State* L, lua_Debug* dbg)
898876
#ifdef DEBUG
899877
if (scriptEngine->current_thread())
900878
scriptEngine->current_thread()->script_hook(L, dbg);
901-
else
902-
scriptEngine->m_stack_is_ready = true;
903879
#endif
904880

905881
if (scriptEngine->m_profiler)
@@ -1067,7 +1043,6 @@ void CScriptEngine::init(ExporterFunc exporterFunc, bool loadGlobalNamespace)
10671043
}
10681044
#endif
10691045
setup_auto_load();
1070-
m_stack_is_ready = true;
10711046

10721047
#if defined(DEBUG) && !defined(USE_LUA_STUDIO)
10731048
#if defined(USE_DEBUGGER)
@@ -1129,7 +1104,6 @@ bool CScriptEngine::process_file_if_exists(LPCSTR file_name, bool warn_if_not_ex
11291104
{
11301105
print_stack();
11311106
Msg("! WARNING: Access to nonexistent variable '%s' or loading nonexistent script '%s'", file_name, S1);
1132-
m_stack_is_ready = true;
11331107
}
11341108
#endif
11351109
add_no_file(file_name, string_length);

src/xrScriptEngine/script_engine.hpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,6 @@ class XRSCRIPTENGINE_API CScriptEngine
105105
#endif
106106
#endif
107107

108-
public:
109-
bool m_stack_is_ready;
110-
111108
private:
112109
static CScriptEngine* GetInstance(lua_State* state);
113110
static bool RegisterState(lua_State* state, CScriptEngine* scriptEngine);
@@ -188,7 +185,7 @@ class XRSCRIPTENGINE_API CScriptEngine
188185
{
189186
int result = 0;
190187

191-
//if (g_LuaDebug.test(1) || message == LuaMessageType::Error)
188+
if (g_LuaDebug.test(1) || message == LuaMessageType::Error)
192189
{
193190
string4096 log;
194191
result = xr_sprintf(log, format, std::forward<Args>(args)...);
@@ -200,8 +197,12 @@ class XRSCRIPTENGINE_API CScriptEngine
200197
m_output.w("\r\n", sizeof("\r\n"));
201198
}
202199

203-
if (message == LuaMessageType::Error)
200+
if (message == LuaMessageType::Error && !logReenterability)
201+
{
202+
logReenterability = true;
204203
print_stack();
204+
logReenterability = false;
205+
}
205206

206207
return result;
207208
}
@@ -210,7 +211,6 @@ class XRSCRIPTENGINE_API CScriptEngine
210211

211212
private:
212213
static void print_error(lua_State* L, int iErrorCode);
213-
static bool onErrorCallback(lua_State* L, pcstr scriptName, int errorCode, pcstr err = nullptr);
214214

215215
public:
216216
static void on_error(lua_State* state);
@@ -229,7 +229,7 @@ class XRSCRIPTENGINE_API CScriptEngine
229229
static int lua_panic(lua_State* L);
230230
static void lua_error(lua_State* L);
231231
static int lua_pcall_failed(lua_State* L);
232-
#if 1 //!XRAY_EXCEPTIONS
232+
#if !XRAY_EXCEPTIONS
233233
static void lua_cast_failed(lua_State* L, const luabind::type_id& info);
234234
#endif
235235
static void lua_hook_call(lua_State* L, lua_Debug* dbg);

0 commit comments

Comments
 (0)