improve lua errors handling (traceback) & lua stack leaks fixes
This commit is contained in:
@@ -79,6 +79,9 @@ dynamic::Value lua::tovalue(State* L, int idx) {
|
|||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case LUA_TFUNCTION:
|
||||||
|
return "<function "+std::to_string(
|
||||||
|
reinterpret_cast<ptrdiff_t>(lua_topointer(L, idx)))+">";
|
||||||
case LUA_TSTRING:
|
case LUA_TSTRING:
|
||||||
return std::string(tostring(L, idx));
|
return std::string(tostring(L, idx));
|
||||||
case LUA_TTABLE: {
|
case LUA_TTABLE: {
|
||||||
@@ -109,23 +112,48 @@ dynamic::Value lua::tovalue(State* L, int idx) {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(
|
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) {
|
static int l_error_handler(lua_State* L) {
|
||||||
if (lua_pcall(L, argc, nresults, 0)) {
|
if (!isstring(L, 1)) { // 'message' not a string?
|
||||||
throw luaerror(tostring(L, -1));
|
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;
|
return nresults == -1 ? 1 : nresults;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lua::call_nothrow(State* L, int argc, int 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));
|
log_error(tostring(L, -1));
|
||||||
|
pop(L);
|
||||||
|
remove(L, handler_pos);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
remove(L, handler_pos);
|
||||||
return nresults == -1 ? 1 : nresults;
|
return nresults == -1 ? 1 : nresults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ namespace lua {
|
|||||||
inline void pop(lua::State* L, int n=1) {
|
inline void pop(lua::State* L, int n=1) {
|
||||||
lua_pop(L, n);
|
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) {
|
inline int gettop(lua::State* L) {
|
||||||
return lua_gettop(L);
|
return lua_gettop(L);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user