improve lua errors handling (traceback) & lua stack leaks fixes

This commit is contained in:
MihailRis 2024-07-24 16:19:14 +03:00
parent 2ec6c8b540
commit fe1ac69b57
2 changed files with 39 additions and 5 deletions

View File

@ -79,6 +79,9 @@ dynamic::Value lua::tovalue(State* L, int idx) {
return number;
}
}
case LUA_TFUNCTION:
return "<function "+std::to_string(
reinterpret_cast<ptrdiff_t>(lua_topointer(L, idx)))+">";
case LUA_TSTRING:
return std::string(tostring(L, idx));
case LUA_TTABLE: {
@ -109,23 +112,48 @@ dynamic::Value lua::tovalue(State* L, int idx) {
}
default:
throw std::runtime_error(
"lua type "+std::string(luaL_typename(L, type))+" is not supported"
"lua type "+std::string(lua_typename(L, type))+" is not supported"
);
}
}
int lua::call(State* L, int argc, int nresults) {
if (lua_pcall(L, argc, nresults, 0)) {
throw luaerror(tostring(L, -1));
static int l_error_handler(lua_State* L) {
if (!isstring(L, 1)) { // 'message' not a string?
return 1; // keep it intact
}
if (get_from(L, "debug", "traceback")) {
lua_pushvalue(L, 1); // pass error message
lua_pushinteger(L, 2); // skip this function and traceback
lua_call(L, 2, 1); // call debug.traceback
}
return 1;
}
int lua::call(State* L, int argc, int nresults) {
int handler_pos = gettop(L) - argc;
pushcfunction(L, l_error_handler);
insert(L, handler_pos);
if (lua_pcall(L, argc, nresults, handler_pos)) {
std::string log = tostring(L, -1);
pop(L);
remove(L, handler_pos);
throw luaerror(log);
}
remove(L, handler_pos);
return nresults == -1 ? 1 : nresults;
}
int lua::call_nothrow(State* L, int argc, int nresults) {
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
int handler_pos = gettop(L) - argc;
pushcfunction(L, l_error_handler);
insert(L, handler_pos);
if (lua_pcall(L, argc, LUA_MULTRET, handler_pos)) {
log_error(tostring(L, -1));
pop(L);
remove(L, handler_pos);
return 0;
}
remove(L, handler_pos);
return nresults == -1 ? 1 : nresults;
}

View File

@ -38,6 +38,12 @@ namespace lua {
inline void pop(lua::State* L, int n=1) {
lua_pop(L, n);
}
inline void insert(lua::State* L, int idx) {
lua_insert(L, idx);
}
inline void remove(lua::State* L, int idx) {
lua_remove(L, idx);
}
inline int gettop(lua::State* L) {
return lua_gettop(L);
}