From 019ebcb85fa5ab03f424e21f6758d8533a5b3126 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 21 May 2009 17:06:11 -0300 Subject: [PATCH] errors in finalizers are propagated with code LUA_ERRGCMM (ERRor in __gc MetaMethod) --- ldo.c | 3 ++- lgc.c | 21 +++++++++++++++------ lua.h | 5 +++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/ldo.c b/ldo.c index a9ff037c..2a0d2592 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.62 2009/04/26 21:55:35 roberto Exp roberto $ +** $Id: ldo.c,v 2.63 2009/04/28 19:04:36 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -60,6 +60,7 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { break; } case LUA_ERRSYNTAX: + case LUA_ERRGCMM: case LUA_ERRRUN: { setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ break; diff --git a/lgc.c b/lgc.c index 9563da82..509415c0 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.51 2009/04/28 19:04:36 roberto Exp roberto $ +** $Id: lgc.c,v 2.52 2009/04/29 17:09:41 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -617,11 +617,12 @@ static void dothecall (lua_State *L, void *ud) { } -static void GCTM (lua_State *L) { +static void GCTM (lua_State *L, int propagateerrors) { global_State *g = G(L); Udata *udata = udata2finalize(g); const TValue *tm = gfasttm(g, udata->uv.metatable, TM_GC); if (tm != NULL && ttisfunction(tm)) { + int status; lu_byte oldah = L->allowhook; lu_mem oldt = g->GCthreshold; L->allowhook = 0; /* stop debug hooks during GC tag method */ @@ -629,7 +630,15 @@ static void GCTM (lua_State *L) { setobj2s(L, L->top, tm); setuvalue(L, L->top+1, udata); L->top += 2; - luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ + if (status == LUA_ERRRUN) { /* is there an error msg.? */ + luaO_pushfstring(L, "error in __gc tag method (%s)", + lua_tostring(L, -1)); + status = LUA_ERRGCMM; /* error in __gc metamethod */ + } + luaD_throw(L, status); /* re-send error */ + } L->allowhook = oldah; /* restore hooks */ g->GCthreshold = oldt; /* restore threshold */ } @@ -637,10 +646,10 @@ static void GCTM (lua_State *L) { /* -** Call all GC tag methods +** Call all GC tag methods (without raising errors) */ void luaC_callAllGCTM (lua_State *L) { - while (G(L)->tobefnz) GCTM(L); + while (G(L)->tobefnz) GCTM(L, 0); } @@ -783,7 +792,7 @@ static l_mem singlestep (lua_State *L) { } case GCSfinalize: { if (g->tobefnz) { - GCTM(L); + GCTM(L, 1); if (g->estimate > GCFINALIZECOST) g->estimate -= GCFINALIZECOST; return GCFINALIZECOST; diff --git a/lua.h b/lua.h index fb725765..2836832b 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.235 2009/04/08 18:04:33 roberto Exp roberto $ +** $Id: lua.h,v 1.236 2009/04/17 14:28:06 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -45,7 +45,8 @@ #define LUA_ERRRUN 2 #define LUA_ERRSYNTAX 3 #define LUA_ERRMEM 4 -#define LUA_ERRERR 5 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 typedef struct lua_State lua_State;