lua-users home
lua-l archive

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


Hi

We often define "objects" that hold some resource, e.g. an open tcp socket to port 9100 of a networked printer (such printers, btw, usually start printing only when the client shuts down the socket).

We e.g. have a prt module to talk to such printers:

local p = prt.open(printer, codepage)

p:print('some text')
p:close()

The "object" returned by prt.open() has a metatable that defines a __gc metamethod, this metamethod would close the open socket if it had not yet been closed by a call to p:close().

The Lua script is called from C code using lua_pcall(). Now we notice a problem:  What if the script contains an error and p:close() is never called?  In this case the connection to the printer remains open until the GC kicks in, which can take long.  And during this time, our networked (ticket) printer is blocked.  To illustrate this imagine the following script being called from C:

local p = prt.open(printer, codepage)

p:print('some text')

- provoke an error (concatenating a nil value)

p:print('hello ' .. nonexistingvariable)

p:close()

lua_pcall() returns an error before p:close() has been called, the object stays in memory, the connection remains open, and, the printer remains blocked.

For now, as a first solution, we call lua_gc(LUA_GCCOLLECT, ...) after lua_pcall(), but is this an expensive operation?  Is there a better way to handle such objects that hold resources?  Should we only call lua_gc() if lua_pcall() returns an error, or always?

How do others that integrate Lua into C programs deal with such a situation?

Is there a way to mark an object to be immedtiately garbage collected when it is no longer used?

- Marc