[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: [PATCH] Lua Leak in OS Library. os.atexit()?
- From: "Robert G. Jakabosky" <bobby@...>
- Date: Sun, 6 Sep 2009 20:17:54 -0700
On Sunday 06, Patrick Donnelly wrote:
> Hi Robert,
>
> On Sun, Sep 6, 2009 at 8:37 PM, Robert G.
>
> Jakabosky<bobby@sharedrealm.com> wrote:
> > On Sunday 06, Luiz Henrique de Figueiredo wrote:
> >> > In my opinion, os.exit() is for exiting quickly and letting the OS
> >> > worry about cleaning up.
> >>
> >> Exactly. Nevertheless, in Lua 5.2, os.exit will accept a flag that tells
> >> whether to close the Lua state.
> >
> > How about an os.atexit(func) function to register Lua functions to called
> > when os.exit() or a normal exit happens. This way Lua scripts can still
> > do resource cleanup if they need/want to. Attached 'atexit.lua' is a
> > simple pure Lua os.atexit() function, it catches both 'os.exit()' and
> > normal exit.
> >
> > Personally I am in the camp of people that like to have all
> > memory/resources released by the application/daemon before it exit's back
> > to the OS. But for simple shell type scripts this is overkill.
> >
> > P.S Yay for money-patching. ;)
>
> Since this can be done in Lua (as you show), why does this need to be
> supported in C?
I think closing the lua_State is the less error prone method of cleanup.
Since any object that needs to cleanup some complex resource should already
have a "__gc" method. I would like to see both the Lua 5.2 os.exit() flag
and os.atexit().
One use of the os.atexit() function that I can think of is a daemon written in
pure Lua which creates a pid file when it starts then deletes that file when
it exits. Or to just log the error code passed to os.exit(code).
The new version of atexit.lua attached now passes the error code from
os.exit() to the atexit functions.
--
Robert G. Jakabosky
local exit_list={}
local exit=os.exit
local function cleanup(rc)
-- call atexit functions in reverse order
for x=#exit_list,1,-1 do
local func = exit_list[x]
func(rc)
exit_list[x] = nil
end
end
-- catch normal exit.
local gc=newproxy(true)
exit_list.gc = gc
gc=getmetatable(gc)
gc.__gc = function() cleanup(0) end
os.exit = function(rc)
rc = rc or 0
cleanup(rc)
exit(rc)
end
os.atexit = function(func)
table.insert(exit_list, func)
end
require("atexit")
print("call atexit")
os.atexit(function(rc)
print("atexit function number 1, rc=" .. rc)
end)
os.atexit(function(rc)
print("atexit function number 2, rc=" .. rc)
end)
os.atexit(function(rc)
print("atexit function number 3, rc=" .. rc)
end)
os.atexit(function(rc)
print("atexit function number 4, rc=" .. rc)
end)
-- GC test.
print "start full GC"
collectgarbage("collect")
collectgarbage("collect")
collectgarbage("collect") -- hehe can't be to sure. ;)
collectgarbage("collect")
print("finished full GC")
rc=arg[1] or nil
if rc ~= nil then
if rc == '0' then
print "call os.exit()"
os.exit() -- test default error code
else
print "call os.exit(rc)"
os.exit(rc) -- test passing error code.
end
print "error error shouldn't get here."
end
print "normal exit no 'os.exit()' call"