I have a dynamic library which I load using dlopen()
and then unload using dlclose()
;
If I dont include any objective c code dlopen()
needs one dlclose()
call which is expected behavior. But when I include any objective c code to target, I have problem that I need to do two dlclose()
calls to the loaded library in order to unload.
Is this something expected behavior? How can I fix it?
I realize that you are using dlopen
, not CFBundle
or NSBundle
. Nevertheless, the *Code Loading Programming Topics* manual says this:
In Cocoa applications, you should not use
CFBundle
routines to load and unload executable code, becauseCFBundle
does not natively support the Objective-C runtime.NSBundle
correctly loads Objective-C symbols into the runtime system, but there is no way to unload Cocoa bundles once loaded due to a runtime limitation.
and this:
Because of a limitation in the Objective-C runtime system,
NSBundle
cannot unload executable code.
This makes me suspect that when you load your library, it registers itself with the Objective-C runtime, and the runtime calls dlopen
on the library again (or somehow increases the library's reference count).
I searched the Objective-C runtime source code and found [this](https://github.com/apple-oss-distributions/objc4/blob/objc4-493.9/runtime/objc-os.m:
// dylibs are not allowed to unload
// ...except those with image_info and nothing else (5359412)
if (result->mhdr->filetype == MH_DYLIB && _hasObjcContents(result)) {
dlopen(result->os.dl_info.dli_fname, RTLD_NOLOAD);
}
So yes, the Objective-C runtime is calling dlopen
on your library specifically to prevent it from being unloaded. If you cheat and call dlclose
twice, you should expect bad things to happen.