lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Mon, Aug 3, 2009 at 9:43 AM, Thomas Harning Jr.<harningt@gmail.com> wrote:
> Checking through this and writing up a quick test (at:
> http://pastebin.com/m40f2d12b),
> I found that if there is an error inside a coroutine, the failure is
> 'absorbed' and when the coroutine is collected, the success
> 'finalizers' get executed.
>
> Running this test set on the old version yield no errors, besides the
> valgrind-detect access to freed memory.
>
> Hopefully this test can be massaged into a more clean test for
> correctness of the patch, but for now, it should work effectively to
> root out incorrect behavior.
In comparing how the different patches work to see if I could fix the
coroutine glitch by myself, I found that some of the cleanup code is
performed in different order... particularly WRT baseline code.

Comparing from 'original' finalizer patch (Nodir) to the newer one
provided by  TNHarris... I'm not sure which is 'correct' or not,
especially ones that alter the Lua internal stack/etc.

diff --git a/src/ldo.c b/src/ldo.c
index 883873c..db52477 100644
--- a/src/ldo.c
+++ b/src/ldo.c

@@ -515,8 +525,8 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
   if (status != 0) {  /* error? */
     L->status = cast_byte(status);  /* mark thread as `dead' */
     luaD_seterrorobj(L, status, L->top);
+    if (L->fin_top >= L->fin_stack) luaD_finalize(L, L->fin_top, 1);
     L->ci->top = L->top;
-    if (L->fin_top != 0) luaD_finalize(L, 1, 1);
   }
   else {

@@ -543,24 +553,25 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
 int luaD_pcall (lua_State *L, Pfunc func, void *u,
                 ptrdiff_t old_top, ptrdiff_t ef) {
   int status;
-  int fin_top = L->fin_top;
   unsigned short oldnCcalls = L->nCcalls;
   ptrdiff_t old_ci = saveci(L, L->ci);
   lu_byte old_allowhooks = L->allowhook;
   ptrdiff_t old_errfunc = L->errfunc;
+  ptrdiff_t old_fin = savefin(L, L->fin_top);
   L->errfunc = ef;
   status = luaD_rawrunprotected(L, func, u);
   if (status != 0) {  /* an error occurred? */
     StkId oldtop = restorestack(L, old_top);
+    StkId fintop = restorefin(L, old_fin);
     luaF_close(L, oldtop);  /* close eventual pending closures */
     luaD_seterrorobj(L, status, oldtop);
+    if (fintop) luaD_finalize(L, fintop, 1);
     L->nCcalls = oldnCcalls;
     L->ci = restoreci(L, old_ci);
     L->base = L->ci->base;
     L->savedpc = L->ci->savedpc;
     L->allowhook = old_allowhooks;
     restore_stack_limit(L);
-    if (L->fin_top > fin_top) luaD_finalize(L, fin_top + 1, 1);
   }
   L->errfunc = old_errfunc;
   return status;

-- 
Thomas Harning Jr.