Hi @pwithnall, thanks for responding.
Yes, we’re dynamically linking everything in (I think?) a completely vanilla way.
I think the issue is that libvips is creating a set of gtypes for various classes it uses. If libvips is unloaded but gobject is not, libvips will attempt to create the gtypes again on reload.
So the sequence is:
- apache starts up
- apache starts
mod_php starts all PHP extensions
vips.so PHP extension uses dlopen() to load
libvips.so creates a set of gtypes for classes, triggering the load and init of
- apache now forks four times to make the worker processes
- Some time later, a user restarts apache with
- Apache shuts down
libgobject.so is linked with
nodelete, so it stays in memory, but other libs are cleared out
- As the new libvips inits, it attempts to create the classes it needs, but they half-exist already (the gobject half of the class) and massive chaos ensues
The solution is to make sure that libraries which use gobject classes are not unloaded and reloaded, either by giving the
RTLD_NODELETE flag to
dlopen(), or by linking the library with the
This means that every library that uses gobject / gtype needs to have logic to detect platforms which need
nodelete (I’ve no idea what *BSD or macOS do about this, or if a similar issue exists on win) and enable it.
This seems like duplication of effort and a chance for subtle errors to creep in. Could a solution be to somehow export knowledge about the status of
nodelete from gobject?
We found and fixed this a while ago, but we’ve just been bitten again after adding support for loadable file format modules to libvips, argh.
Perhaps another fix would be for gmodule to set
RTLD_NODELETE when it
dlopen()s a module? Modules that gmodule loads are very likely to be gobject users, so won’t be unloadable.