Workaround dlopen(NULL, 0) brokenness
Submitted by Julio Merino
First, a bit of background about where the problem exposes, which may seem completely unrelated to glib. When using Evolution under NetBSD, many widgets (but not all) in the Settings dialog can't be created. This is because the initialization function for them can't be located by libglade (the library used to create them at runtime).
libglade uses the global symbol table of a program, returned by g_module_open(NULL, 0), to locate those initialization functions. This works properly in almost all programs (because the functions are located in the binary itself or in libraries linked at build time), but fails in Evolution (because the functions are located in libraries dlopen'ed at run time).
Quoting NetBSD's dlopen(3) manpage:
If the first argument is NULL, dlopen() returns a handle on the global symbol object. This object provides access to all symbols from an ordered set of objects consisting of the original program image and any dependencies loaded during startup.
Note that it says nothing about searching the symbol in dlopen'ed objects. This behavior is not correct, according to POSIX:
It will be fixed, some day. But for now, and for not-so-old version of NetBSD, the function is broken, meaning that evolution (and probably other programs!) won't work properly. Note that this might be broken in other systems, too.
However, because of glib's abstraction of loadable modules, this broken behavior can be easily worked around from it: glib keeps track of all open modules so... when a program tries to query a symbol from the main module (opened with dlopen(NULL, 0) and pointed by in the code by the main_module variable) it can query all of them in a loop until the symbol is found, or no more modules remain. That way, it simulates the right dlopen(NULL, 0) behavior in a transparent way to applications.
As the library already has a workaround for broken RTLD_GLOBAL usage, I feel this problem can also be fixed in glib, together that one.