lua-users home
lua-l archive

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


Mark Hamburg wrote:
> Interestingly, the RVM version seems to fix an error in Lua 5.1 in which in
> the following code the value of file in the above finalizer has been rebound
> to 1:

Gee, this is a cute one. And very subtle. Actually it's a new bug in my
code that inadvertently fixes an old bug in the original code.

In your code processWithFinalizer is TAILCALL'ed from withFileDo.
All upvalues within withFileDo (e.g. file) have to be closed before
executing the tailcall. But this does not work properly when tailcalling
a varargs function (such as processWithFinalizer).

The original Lua 51w4 code derives the new base = ci->base from the new
frame (which is not equal to ci->func+1 for vararg functions) and runs
luaF_close() too high in the stack (i.e. the upvalue for 'file' points
to a stale stack entry, soon to be overwritten by the tailcalled function).

In my patch I adjust ci->base, but forgot to set base (luckily the stack
did not get reallocated here). But this has the side effect of running
luaF_close() with the proper base. Alas, one really needs to account for
stack reallocation. So ...

Patch to my patch appended. Will update the Wiki asap.


--- lua51w4-rvm/src/lvm.c.orig	2005-02-15 09:51:14.000000000 +0100
+++ lua51w4-rvm/src/lvm.c	2005-02-17 14:00:51.076513824 +0100
@@ -611,8 +611,8 @@
           StkId func = ci->func;
           StkId pfunc = (ci+1)->func;  /* previous function index */
           ptrdiff_t delta = (char *)pfunc - (char *)func;
+          if (L->openupval) luaF_close(L, ci->base);
           L->base = ci->base = (StkId)((char *)((ci+1)->base) - delta);
-          if (L->openupval) luaF_close(L, base);
           for (aux = 0; pfunc+aux < L->top; aux++)  /* move frame down */
             setobjs2s(L, func+aux, pfunc+aux);
           ci->top = L->top = func+aux;  /* correct top */