RTLD_LOCAL and dynamic_cast for Linux

We have a plugin that consists of several shared libraries in our application that we need to update while the application is running. For performance reasons, we download and start using the new plugin before unloading the old plugin, and only when all threads are completed using the old plugin do we unload it. Since the libraries of the new plugin and the old plugin have the same characters, we dlopen() with RTLD_LOCAL . If we do not, the new plugin will randomly call characters from the old plugin from internal functions.

One plugin library does dynamic_cast() on an object that was created by another plugin library. This works on HP-UX, AIX, Solaris, and Windows, but not Linux. As far as I understand, this is because all of these OSs (compilers) use the class name for type comparisons (in dynamic_cast() ), but Linux uses name string addresses for this comparison (to improve performance), and since each library has its own object type_info (since it was loaded using RTLD_LOCAL ), the addresses are different, and so the same types do not seem to match dynamic_cast() .

Is there a way to do one of the following:

  • Make type_info only type_info objects, as if RTLD_GLOBAL was specified RTLD_GLOBAL .
  • type_info compiler use class name comparisons instead of type_info addresses to compare between types.

? The compiler we use is:

 $ icpc -V Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.0.084 Build 20101006 Copyright (C) 1985-2010 Intel Corporation. All rights reserved. 
+4
source share
2 answers

Well, what we finally did was sort of getting around the problem.

We added to the classes we want dynamic_cast() two static functions:

 static MyClass* doNew(); static MyClass* doDynCast(MyBase*); 

They were implemented in the cpp file, in which the new , dynamic_cast() and type_info in the same type_info and thus made dynamic_cast() solve the problem.

This solution was enough for our particular case, but if someone has a more general solution, it will be welcome.

Another option that we found is to put the entire implementation of the class in a cpp file so that the typeinfo symbol typeinfo present in only one library, and all other libraries refer only to it. This results in successful dynamic_cast() .

+4
source

Unfortunately, since type_info structures are weak characters local to the library that creates them, it is not easy to make dynamic_cast work. You can try to manipulate where an instance of the vtable class (and type_info) is created; on GCC, this can be done by guaranteeing the first non-built-in function in the class (in the order of definition) is defined only in the common shared dependency library. If your class does not have built-in functions, create a dummy to make this generation happen. Please note, however, that I have not tested this and therefore cannot guarantee that it will work. Also, it depends on the compiler; I do not know what the Intel compiler does.

You could, of course, implement your own alternative dynamic cast mechanism using class names; There are a number of libraries that also do this, such as Qt qobject_cast .

+2
source

All Articles