objective-ccmacoscocoadylib

unload dynamic library needs two dlclose() calls?


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?


Solution

  • 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, because CFBundle 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.