lua-users home
lua-l archive

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


> I am trying to understand this test case in 'locals.lua'
> 
>   local x = 0
>   local y = 0
>   co = coroutine.wrap(function ()
>     local xx <close> = func2close(function () y = y + 1; error("YYY") end)
>     local xv <close> = func2close(function () x = x + 1; error("XXX") end)
>       coroutine.yield(100)
>       return 200
>   end)
>   assert(co() == 100); assert(x == 0)
>   local st, msg = pcall(co)
>   assert(x == 2 and y == 1)   -- first close is called twice
> 
> My question is this:
> 
> Why is the 'first close is called twice'?

Because it raises an error. When closing a variable normally
(that is, not handling an error), the call to the closing method
may cause a stack overflow, and then the closing method will
not be executed. If that happens, Lua will call the closing method
again after the error (which opened space in the stack).
Lua does not distinguish between stack errors and other errors when
calling the closing method, so any error while running it will call it
again.

A similar argument applies to a memory error. If there is a memory
error while running the closing method, there is a good chance that
the frames freed after the error release enough memory to allow
the closing method to run. So it is worth trying once more.

This is documented:

    If there is any error while running a closing method,
    that error is handled like an error in the regular code
    where the variable was defined.
    However, Lua may call the method one more time.

(If you follow our recommendation that closing methods should be
backed-up by finalizers, they already should be idempotent.)

-- Roberto