Support table errors.

LuaSocket wraps error messages raised by newtry() in a table and unpacks
them later so that (string) errors raised by 3rd-party code can be
passed through as-is. This obviously didn't work when the 3rd-party code
raised a table as an error message. This change sets a private metatable
on all wrapped LuaSocket exceptions to distinguish them from 3rd-party
table errors.
This commit is contained in:
Philipp Janda 2016-02-21 11:59:44 +01:00
parent bf13ec7fd4
commit d075e7322f

View File

@ -12,7 +12,7 @@
#if LUA_VERSION_NUM < 502 #if LUA_VERSION_NUM < 502
#define lua_pcallk(L, na, nr, err, ctx, cont) \ #define lua_pcallk(L, na, nr, err, ctx, cont) \
((void)ctx,(void)cont,lua_pcall(L, na, nr, err)) (((void)ctx),((void)cont),lua_pcall(L, na, nr, err))
#endif #endif
#if LUA_VERSION_NUM < 503 #if LUA_VERSION_NUM < 503
@ -39,12 +39,11 @@ static luaL_Reg func[] = {
* Try factory * Try factory
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static void wrap(lua_State *L) { static void wrap(lua_State *L) {
lua_newtable(L); lua_createtable(L, 1, 0);
lua_pushnumber(L, 1); lua_pushvalue(L, -2);
lua_pushvalue(L, -3); lua_rawseti(L, -2, 1);
lua_settable(L, -3); lua_pushvalue(L, lua_upvalueindex(2));
lua_insert(L, -2); lua_setmetatable(L, -2);
lua_pop(L, 1);
} }
static int finalize(lua_State *L) { static int finalize(lua_State *L) {
@ -66,7 +65,8 @@ static int do_nothing(lua_State *L) {
static int global_newtry(lua_State *L) { static int global_newtry(lua_State *L) {
lua_settop(L, 1); lua_settop(L, 1);
if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing); if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing);
lua_pushcclosure(L, finalize, 1); lua_pushvalue(L, lua_upvalueindex(1));
lua_pushcclosure(L, finalize, 2);
return 1; return 1;
} }
@ -74,13 +74,16 @@ static int global_newtry(lua_State *L) {
* Protect factory * Protect factory
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static int unwrap(lua_State *L) { static int unwrap(lua_State *L) {
if (lua_istable(L, -1)) { if (lua_istable(L, -1) && lua_getmetatable(L, -1)) {
lua_pushnumber(L, 1); int r = lua_rawequal(L, -1, lua_upvalueindex(2));
lua_gettable(L, -2); lua_pop(L, 1);
if (r) {
lua_pushnil(L); lua_pushnil(L);
lua_insert(L, -2); lua_rawgeti(L, -2, 1);
return 1; return 1;
} else return 0; }
}
return 0;
} }
static int protected_finish(lua_State *L, int status, lua_KContext ctx) { static int protected_finish(lua_State *L, int status, lua_KContext ctx) {
@ -110,7 +113,9 @@ static int protected_(lua_State *L) {
} }
static int global_protect(lua_State *L) { static int global_protect(lua_State *L) {
lua_pushcclosure(L, protected_, 1); lua_settop(L, 1);
lua_pushvalue(L, lua_upvalueindex(1));
lua_pushcclosure(L, protected_, 2);
return 1; return 1;
} }
@ -118,6 +123,9 @@ static int global_protect(lua_State *L) {
* Init module * Init module
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
int except_open(lua_State *L) { int except_open(lua_State *L) {
luaL_setfuncs(L, func, 0); lua_newtable(L); /* metatable for wrapped exceptions */
lua_pushboolean(L, 0);
lua_setfield(L, -2, "__metatable");
luaL_setfuncs(L, func, 1);
return 0; return 0;
} }