The question is as in the title and the following is the background:
On Linux, I'm trying to use dlopen() etc to build a C++ .so plugin framework that has a minimal and clean interface. That means:
- Loading the plugin and creating a (C++) singleton object from the plugin simply involves calling a function
makePluginObject()with a path to the .so file being loaded and getting back a pointer to the object. Under the hood, this function calls dlopen() followed by the actual object allocation & construction. The object is of a C++ class whose implementation is in the .so. - Later, the user can just delete (calling dtor) the pointer to do all the necessary cleanup, including dlclose(), which is done by the dtor. This would be implemented by calling dlclose() in the object's dtor. (Under the hood, the handle from dlopen() was passed to the object during
makePluginObject().) Crucially, there is no additional shutdown/teardown function for the user to explicitly call.
The above design probably means that the code calling dlclose() is in the .so being dlopen'ed. The key question is this: Is it OK for code to call dlclose() on itself? I wonder because a naive implementation of dlclose() would unmap from memory the code that is still being run during object destruction.
It's important that the user interface remains this simple. The user just needs to call makePluginObject() and delete the resulting pointer when he is done. If a teardown function is introduced that the user has to explicitly call after deleting the object, then the interface is much heavier and the burden on the user is much more. I know how to do things if an explicit teardown function is allowed and this question is not about that use case.
In my experiments, there were no crashes, but it seemed that dlclose() didn't really do anything because valgrind reported a lot of reachable memory associated with my call to dlopen().