fix(lua): segfault on error handler, new error handler system adopted
This commit is contained in:
parent
527f159ff3
commit
d558f166f9
3 changed files with 37 additions and 59 deletions
|
@ -13,6 +13,8 @@
|
|||
|
||||
int script_wait(lua_State*);
|
||||
int script_delay(lua_State*);
|
||||
int script_wrapper(lua_State*);
|
||||
int script_errhandler(lua_State*);
|
||||
|
||||
Script::Script(): Instance(&TYPE) {
|
||||
source = "print(\"Hello, world!\")";
|
||||
|
@ -52,41 +54,11 @@ void Script::Run() {
|
|||
|
||||
lua_pop(Lt, 1); // _G
|
||||
|
||||
// Load source and push onto thread stack as function ptr
|
||||
// luaL_loadstring(Lt, source.c_str());
|
||||
luaL_loadbuffer(Lt, source.c_str(), source.size(), scriptContext->RegisterScriptSource(shared<Script>()).c_str());
|
||||
// Load source and push onto thread stack as upvalue for wrapper closure
|
||||
luaL_loadbuffer(Lt, source.c_str(), source.size(), this->GetFullName().c_str());
|
||||
lua_pushcclosure(Lt, script_wrapper, 1);
|
||||
|
||||
int status = lua_resume(Lt, 0);
|
||||
if (status > LUA_YIELD) {
|
||||
lua_Debug dbg;
|
||||
lua_getstack(Lt, 1, &dbg);
|
||||
lua_getinfo(Lt, "S", &dbg);
|
||||
|
||||
std::weak_ptr<Script> source = scriptContext->GetScriptFromSource(dbg.source);
|
||||
|
||||
std::string errorMessage = lua_tostring(Lt, -1);
|
||||
if (!source.expired())
|
||||
errorMessage = source.lock()->GetFullName() + errorMessage.substr(errorMessage.find(':'));
|
||||
|
||||
Logger::error(errorMessage);
|
||||
lua_pop(Lt, 1); // Pop return value
|
||||
|
||||
Logger::traceStart();
|
||||
|
||||
int stack = 1;
|
||||
while (lua_getstack(Lt, stack++, &dbg)) {
|
||||
lua_getinfo(Lt, "nlSu", &dbg);
|
||||
|
||||
std::weak_ptr<Script> source = scriptContext->GetScriptFromSource(dbg.source);
|
||||
if (source.expired()) {
|
||||
Logger::trace(dbg.source, dbg.currentline);
|
||||
} else {
|
||||
Logger::trace(source.lock()->GetFullName(), dbg.currentline, &source);
|
||||
}
|
||||
}
|
||||
|
||||
Logger::traceEnd();
|
||||
}
|
||||
lua_resume(Lt, 0);
|
||||
|
||||
lua_pop(L, 1); // Pop the thread
|
||||
}
|
||||
|
@ -123,3 +95,33 @@ int script_delay(lua_State* L) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int script_wrapper(lua_State* L) {
|
||||
lua_pushcfunction(L, script_errhandler);
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
lua_pcall(L, 0, 0, -2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int script_errhandler(lua_State* L) {
|
||||
std::string errorMessage = lua_tostring(L, -1);
|
||||
Logger::error(errorMessage);
|
||||
|
||||
// Traceback
|
||||
|
||||
Logger::traceStart();
|
||||
|
||||
lua_Debug dbg;
|
||||
int stack = 1;
|
||||
while (lua_getstack(L, stack++, &dbg)) {
|
||||
lua_getinfo(L, "nlSu", &dbg);
|
||||
if (strcmp(dbg.what, "C") == 0)
|
||||
continue; // Ignore C frames
|
||||
|
||||
Logger::trace(dbg.source, dbg.currentline);
|
||||
}
|
||||
|
||||
Logger::traceEnd();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -105,11 +105,7 @@ void ScriptContext::RunSleepingThreads() {
|
|||
// Time args
|
||||
lua_pushnumber(sleep.thread, float(tu_clock_micros() - sleep.timeYieldedWhen) / 1'000'000);
|
||||
lua_pushnumber(sleep.thread, float(tu_clock_micros()) / 1'000'000);
|
||||
int status = lua_resume(sleep.thread, 2);
|
||||
if (status > LUA_YIELD) {
|
||||
Logger::error(lua_tostring(sleep.thread, -1));
|
||||
lua_pop(sleep.thread, 1); // Pop return value
|
||||
}
|
||||
lua_resume(sleep.thread, 2);
|
||||
|
||||
// Remove thread
|
||||
deleted = true;
|
||||
|
@ -134,23 +130,6 @@ void ScriptContext::RunSleepingThreads() {
|
|||
schedTime = tu_clock_micros() - startTime;
|
||||
}
|
||||
|
||||
std::string ScriptContext::RegisterScriptSource(std::shared_ptr<Script> script) {
|
||||
// If it has already been registered, reference it here
|
||||
for (auto& [id, script2] : scriptSources) {
|
||||
if (!script2.expired() && script2.lock() == script)
|
||||
return "=f" + std::to_string(id);
|
||||
}
|
||||
|
||||
int id = lastScriptSourceId++;
|
||||
scriptSources[id] = script;
|
||||
return "=f" + std::to_string(id);
|
||||
}
|
||||
|
||||
std::weak_ptr<Script> ScriptContext::GetScriptFromSource(std::string source) {
|
||||
int id = std::stoi(source.c_str() + 2);
|
||||
return scriptSources[id];
|
||||
}
|
||||
|
||||
// https://www.lua.org/source/5.1/lbaselib.c.html
|
||||
static int g_print(lua_State* L) {
|
||||
std::string buf;
|
||||
|
|
|
@ -19,7 +19,6 @@ class DEF_INST_SERVICE ScriptContext : public Service {
|
|||
AUTOGEN_PREAMBLE
|
||||
|
||||
std::vector<SleepingThread> sleepingThreads;
|
||||
std::map<int, std::weak_ptr<Script>> scriptSources;
|
||||
int lastScriptSourceId = 0;
|
||||
protected:
|
||||
void InitService() override;
|
||||
|
@ -32,8 +31,6 @@ public:
|
|||
lua_State* state;
|
||||
void PushThreadSleep(lua_State* thread, float delay);
|
||||
void RunSleepingThreads();
|
||||
std::string RegisterScriptSource(std::shared_ptr<Script>);
|
||||
std::weak_ptr<Script> GetScriptFromSource(std::string source);
|
||||
|
||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<ScriptContext>(); };
|
||||
};
|
Loading…
Add table
Reference in a new issue