diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp index 4aec7909a..a56519aca 100644 --- a/src/common/runtime.cpp +++ b/src/common/runtime.cpp @@ -130,6 +130,31 @@ void luax_printstack(lua_State *L) std::cout << i << " - " << luaL_typename(L, i) << std::endl; } +int luax_traceback(lua_State *L) +{ + if (!lua_isstring(L, 1)) // 'message' not a string? + return 1; // keep it intact + + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) + { + lua_pop(L, 1); + return 1; + } + + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) + { + lua_pop(L, 2); + return 1; + } + + 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; +} + bool luax_isarrayoftables(lua_State *L, int idx) { if (!lua_istable(L, idx)) diff --git a/src/common/runtime.h b/src/common/runtime.h index 7082530fb..e728ea0ae 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -106,6 +106,11 @@ Reference *luax_refif(lua_State *L, int type); **/ void luax_printstack(lua_State *L); +/** + * Traceback function for use with lua_pcall. Calls debug.traceback. + **/ +int luax_traceback(lua_State *L); + /** * Gets whether the value at idx is an array of tables. **/ diff --git a/src/modules/thread/LuaThread.cpp b/src/modules/thread/LuaThread.cpp index 3126a71fb..479aaa363 100644 --- a/src/modules/thread/LuaThread.cpp +++ b/src/modules/thread/LuaThread.cpp @@ -66,6 +66,9 @@ void LuaThread::threadFunction() luax_require(L, "love.filesystem"); lua_pop(L, 1); + lua_pushcfunction(L, luax_traceback); + int tracebackidx = lua_gettop(L); + if (luaL_loadbuffer(L, (const char *) code->getData(), code->getSize(), name.c_str()) != 0) error = luax_tostring(L, -1); else @@ -77,7 +80,7 @@ void LuaThread::threadFunction() args.clear(); - if (lua_pcall(L, pushedargs, 0, 0) != 0) + if (lua_pcall(L, pushedargs, 0, tracebackidx) != 0) error = luax_tostring(L, -1); }