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_wait(lua_State*);
|
||||||
int script_delay(lua_State*);
|
int script_delay(lua_State*);
|
||||||
|
int script_wrapper(lua_State*);
|
||||||
|
int script_errhandler(lua_State*);
|
||||||
|
|
||||||
Script::Script(): Instance(&TYPE) {
|
Script::Script(): Instance(&TYPE) {
|
||||||
source = "print(\"Hello, world!\")";
|
source = "print(\"Hello, world!\")";
|
||||||
|
@ -52,41 +54,11 @@ void Script::Run() {
|
||||||
|
|
||||||
lua_pop(Lt, 1); // _G
|
lua_pop(Lt, 1); // _G
|
||||||
|
|
||||||
// Load source and push onto thread stack as function ptr
|
// Load source and push onto thread stack as upvalue for wrapper closure
|
||||||
// luaL_loadstring(Lt, source.c_str());
|
luaL_loadbuffer(Lt, source.c_str(), source.size(), this->GetFullName().c_str());
|
||||||
luaL_loadbuffer(Lt, source.c_str(), source.size(), scriptContext->RegisterScriptSource(shared<Script>()).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);
|
lua_resume(Lt, 0);
|
||||||
|
|
||||||
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_pop(L, 1); // Pop the thread
|
lua_pop(L, 1); // Pop the thread
|
||||||
}
|
}
|
||||||
|
@ -121,5 +93,35 @@ int script_delay(lua_State* L) {
|
||||||
// Schedule next run
|
// Schedule next run
|
||||||
scriptContext->PushThreadSleep(Lt, secs);
|
scriptContext->PushThreadSleep(Lt, secs);
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
|
@ -105,11 +105,7 @@ void ScriptContext::RunSleepingThreads() {
|
||||||
// Time args
|
// Time args
|
||||||
lua_pushnumber(sleep.thread, float(tu_clock_micros() - sleep.timeYieldedWhen) / 1'000'000);
|
lua_pushnumber(sleep.thread, float(tu_clock_micros() - sleep.timeYieldedWhen) / 1'000'000);
|
||||||
lua_pushnumber(sleep.thread, float(tu_clock_micros()) / 1'000'000);
|
lua_pushnumber(sleep.thread, float(tu_clock_micros()) / 1'000'000);
|
||||||
int status = lua_resume(sleep.thread, 2);
|
lua_resume(sleep.thread, 2);
|
||||||
if (status > LUA_YIELD) {
|
|
||||||
Logger::error(lua_tostring(sleep.thread, -1));
|
|
||||||
lua_pop(sleep.thread, 1); // Pop return value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove thread
|
// Remove thread
|
||||||
deleted = true;
|
deleted = true;
|
||||||
|
@ -134,23 +130,6 @@ void ScriptContext::RunSleepingThreads() {
|
||||||
schedTime = tu_clock_micros() - startTime;
|
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
|
// https://www.lua.org/source/5.1/lbaselib.c.html
|
||||||
static int g_print(lua_State* L) {
|
static int g_print(lua_State* L) {
|
||||||
std::string buf;
|
std::string buf;
|
||||||
|
|
|
@ -19,7 +19,6 @@ class DEF_INST_SERVICE ScriptContext : public Service {
|
||||||
AUTOGEN_PREAMBLE
|
AUTOGEN_PREAMBLE
|
||||||
|
|
||||||
std::vector<SleepingThread> sleepingThreads;
|
std::vector<SleepingThread> sleepingThreads;
|
||||||
std::map<int, std::weak_ptr<Script>> scriptSources;
|
|
||||||
int lastScriptSourceId = 0;
|
int lastScriptSourceId = 0;
|
||||||
protected:
|
protected:
|
||||||
void InitService() override;
|
void InitService() override;
|
||||||
|
@ -32,8 +31,6 @@ public:
|
||||||
lua_State* state;
|
lua_State* state;
|
||||||
void PushThreadSleep(lua_State* thread, float delay);
|
void PushThreadSleep(lua_State* thread, float delay);
|
||||||
void RunSleepingThreads();
|
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>(); };
|
static inline std::shared_ptr<Instance> Create() { return std::make_shared<ScriptContext>(); };
|
||||||
};
|
};
|
Loading…
Add table
Reference in a new issue