lua-users home
lua-l archive

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


On Tue, Nov 24, 2015 at 10:52 AM, Viacheslav Usov <via.usov@gmail.com> wrote:
> On Tue, Nov 24, 2015 at 3:27 PM, Patrick Donnelly <batrick@batbytes.com>
>
>> Sorry, one more message to respond to the "breaks a major assumption": are
>> you talking about the issue of calling __gc more than once on a object?
>
> The major assumption is that once the finalizer is called (and it does not
> resurrect the object), the object is never accessible by any user code, and
> so no library routine, including "close" and __gc, will ever be called with
> that object.
>
> That assumption is not 100% correct because a dedicated user (given a
> lenient library) could still obtain __gc and call it. I doubt this is widely
> understood by everybody who writes code callable from Lua, but the
> implications are not severe because this will not happen in normal use. Same
> for handling multiple "close" calls: they won't happen in normal use.

A dedicated user could also use proxy userdata and weak tables to
force a non-transient resurrection (to use the Lua manual's terms).
Have the proxy userdata's lifetime tied to the userdata you want to
resurrect. Use the proxy's __gc metamethod to force resurrection:

$ lua
Lua 5.3.1  Copyright (C) 1994-2015 Lua.org, PUC-Rio
> do
>> local f = io.open("/dev/null");
>> local t = setmetatable({}, {__mode = "k"})
>> t[f] = setmetatable({}, {__gc = function() print 'resurrecting f'; _G.file = f; end})
>> end
> collectgarbage "collect"; collectgarbage "collect";
resurrecting f
> print(file)
file (closed)

For Lua 5.3 we use a table instead of a proxy userdata.

The user may not be able to call a protected __gc metamethod more than
once but they can still call any method on a "closed" object. All done
with simple Lua primitives. It's easy to see how this could be done
accidentally. All libraries should handle closed objects robustly for
all methods.

-- 
Patrick Donnelly