[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: module loading in C
- From: Hans van der Meer <H.vanderMeer@...>
- Date: Fri, 5 Sep 2008 13:56:44 +0200
Roberto Ierusalimschy <roberto@...> wrote
It is a bit more complicated than creating userdata either before or
after loading the library module, though I would not go sofar as
calling my program 'weird'. Let me explain.
A crash occurs under these circumstances:
- a program is in the final phase of its execution where its state
- a library module (=userdata) is unloaded in the cleanup (__gc=gctm)
- a userdata calls its __gc method where it needs a function in the
library just unloaded
- segmentation fault results
So, the userdata is being finalized after the module, right? Either
it was created after the module, and then we have a bug in Lua (that
should finalize it before the module), or it was created before the
module, and then we have a weird program (where a userdata needs in
its finalizer a function from a module that was not loaded yet). Can
you tell what is your case?
I am developing an upwards compatible io-module, where the lowlevel
calls (those to the stdio functions) are split off into a submodule or
backend. The higher level functions like open, read, etc. rely on
submodule functions for the bare minimum of reading and writing. This
setup allows for different backends, which then operate transparently
to the file commands in Lua programs; an optional parameter on the
open call can select the backend. At the moment I have three
submodules: for stdio, for reading and writing zlib compressed files
and for in-memory files.
Calling open(filename,...) in the main module allocates userdata to
hold the information and then proceeds to open the file in the
submodule's open function. In retrieving that open function the
submodule is loaded, if not yet in memory (a not uncommon tactics of
lazy loading). After that, new userdata in the same filetype finds the
submodule loaded already. Thus, at no point in the program are there
userdata finalizing through a module not yet loaded at that moment.
But yes, the first userdata is created before the library module it
needs, is loaded by the main module.
In a previous post you mentioned the fact that the userdata unloading
is done in reverse order of creation:
In the cleanup phase, references do not prevent a module from being
finalized; otherwise the clean up would be a regular collection and
would not collect everything. However, finalizers are not called in
arbitrary order, but in reverse order of their creation. If module A
is loaded before module B (so that B may depend on A), then module A
will be unloaded after module B.
In the expectation that this does not only applies to modules but to
all userdata as a whole, I changed my program to force submodule
loading before the creation of the first userdata that depends on it.
Then indeed all is well. So, thank you for your helpful remarks that
now completely solve the problem, without a need to change the Lua-
code. By the way, in the process I learned a lot about Lua!
However, allow me one final remark. It all depends on the reverse
order of calling the userdata __gc functions. If at any time in the
future a new implementation of the collection/clearing phase changes
that, then programs like this will break again. How certain can one be
that this will not happen? I therefore suggest that a change is made
to unload libraries in a last separate step, possibly in Lua 5.2.
Hans van der Meer