10

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?

Sangeeth Saravanaraj
  • 16,027
  • 21
  • 69
  • 98
RLT
  • 4,219
  • 4
  • 37
  • 91
  • Are you sure that your library is not `dlopen`-ed twice in a hidden way? Or maybe a bug -e.g. memory leak- is overwriting memory near the `dlopen`-ed handle? – Basile Starynkevitch Jan 09 '12 at 18:13
  • dlopen keeps a reference count of on the library handle. If dlopen was done twice, it will require two dlclose() to unload the library. Is it possible the dynamic library is required if you include the obj-C code ? In which case the first dlopen may be done when you run your program – Finslicer Jan 09 '12 at 18:13
  • Yes I am sure its not dlopened twice. You can try a simple program in main with dlopen followed by dlclose with dynamic library which has objective c code. – RLT Jan 09 '12 at 18:26
  • @Finslicer: I am sure that dynamic library is not required in start of program. As I said, even a simple main with dlopen and then dlclose does not work as expected if there is objective c code. – RLT Jan 09 '12 at 18:28

1 Answers1

32

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:

// 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.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848