lua-users home
lua-l archive

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

On Mon, Aug 3, 2009 at 6:20 PM, TNHarris<> wrote:
> Yes, that was the problem. And also in resetstack, the same thing:
> diff -urN -x '*.o' -x '*.a' -x '*.exe' -x '*.lua' lua.orig/src/ldo.c
> lua.mod/src/ldo.c --- lua.orig/src/ldo.c        2008-01-18 17:31:22.000000000 -0500
> +++ lua.mod/src/ldo.c   2009-08-02 06:57:33.526611200 -0400
> @@ -83,6 +83,8 @@
>   L->base = L->ci->base;
>   luaF_close(L, L->base);  /* close eventual pending closures */
>   luaD_seterrorobj(L, status, L->base);
> +  L->allowhook = 0;
> +  if (L->fin_top) luaD_finalize(L, L->fin_stack, 1);
>   L->nCcalls = L->baseCcalls;
>   L->allowhook = 1;
>   restore_stack_limit(L);
>> 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.
> Mostly, this is because of the change from a base+offset stack to stack
> pointers. But when it comes to calling finalizers after an error, I'm
> not too sure how the Lua state and call info should be massaged to avoid
> "Bad Things". I guessed on a lot of it and, if it appeared to work, let
> it be. I think the order should be to clean up from the callee, invoke
> finalizers, restore the caller state.
One thing I found that affects both patches and am not at all sure on
how it should be handled... when a finalizer throws, odd things
happen.  It appears that the first error in a finalizer can be handled
(maybe due to an outer pcall I'm using), but a second one causes the
lua interpreter's exception handler to get used.
My best guess is that when the finalization stack runs into an
exception, it performs the longjmp and then starts the process of
cleaning up finalizers all over again.

IN a quick little test (in the same test framework I had before):
test("Error in finally", function()
	finally(print, 'HELLO1')
	finally(function() error("FAIL IN FINALIZE1") end)
	finally(function() error("FAIL IN FINALIZE2") end)
	finally(print, 'HELLO'2)
end, 0, 0, 0)

If I comment out the second error, things seem to go ok and I get the
following output:
HELLO1	test-correct.lua:87: FAIL IN FINALIZE1

However, if I do not and throw in that second finalizer, i get:
HELLO1	test-correct.lua:87: FAIL IN FINALIZE1
lua-5.1.4-fin1/src/lua: test-correct.lua:87: FAIL IN FINALIZE1

Notice that FAIL IN FINALIZE2 is not the error, but fail in finalize1
is called again.  It looks like when the first fail in finalize
occurred, it managed to mark that the new top of the cleanup stack...
however two errors in a row (?) caused it to mark the top of the stack
for the previous cleanup....
I 'think' that finalizers should effectively be run in a 'pcall'
environment... but that would probably kill performance.  Perhaps it
should be assumed that if you throw in a finalizer and don't catch
within... expect bad things.

How do hooks handle exceptions?  I suspect they behave similarly...
(cause the outer pcall to get invoked), but they do not have the
"interesting" state issue that finalization stacks do.

I'm tempted to rework this patch such that you can isolate cleanup/etc
from the inner code, but have callbacks on:

 * function exit
 * function error-based exit
 * coroutine error/exit
 * coroutine collection
Thomas Harning Jr.