6

Is it possible for a running c++ based process to reload a c++ based dynamic library using dlopen.

The running process polls for a new version of the dynamic library (with the same API). once such file is detected, the following set of actions are taking place :

  1. The older Library gets unloaded using dlclose
  2. The newer dylib is copied and override the file of the older version.
  3. The process loads the newer version from that location using dlopen
  4. Setting the function pointer variables according to dlsym from the newly loaded library.

In the last stage, I actually get the desired API and place it in function pointer from my main code to be used later.

However, it seems like my program is unexpectedly gets crashed after the third phase. is it possible that the dlclose part leave some remnants of the older library in the process virtual space ? is there any better way to do so ?

by the way, in Windows it's working just fine using LoadLibrary, FreeLibrary and GetProcAddress instead of dlopen, dlclose and dlsym.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Zohar81
  • 4,554
  • 5
  • 29
  • 82
  • but if I still want to reload new library version, can I do so by changing the file name, for example by adding its version after the suffix ? – Zohar81 Mar 14 '18 at 15:22
  • Yes, but your issue is probably that you didn't reload the functions and objects you got from `dlsym`. – Quentin Mar 14 '18 at 15:39
  • @Quentin, I actually take the API I need using `dlsym` (see updated question), isn't there any way that the linker gets confused with the older symbols (that have the same name) ? – Zohar81 Mar 14 '18 at 15:49

1 Answers1

5

it seems like my program is unexpectedly gets crashed after the third phase. is it possible that the dlclose part leave some remnants of the older library in the process virtual space?

It is possible. Objects with function pointers to functions and objects with virtual functions defined in the library being unloaded are going to end up with invalid pointers. Even worse, one can attach a new facet to a standard stream (e.g. std::cout) and then unload the shared library implementing the facet. Later on it would crash when using std::cout in a unrelated place (true story). So, you must be in total control of what the shared library does.

Also, dlopen must be called with RTLD_LOCAL, so that nothing else can (accidentally) use the symbols of the shared library being loaded and prevent it from unloading. You must read and understand man dlopen if you do such feats.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • 2
    GCC may also output [unique symbols](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66830) which can prevent unloading *even if* `RTLD_LOCAL` is used. These show up as `u` when using `nm`. Most commonly, these are `static` variables in `inline` functions and/or function templates. We have this problem with header-only libraries such as parts of Boost but coworkers of mine also managed to create these. The thing is that if the plugin is the first DSO to introduce them, it can never be unloaded. `dlclose` succeeds but the binary remains mapped. – Arne Vogel Mar 14 '18 at 16:32