On Fri, 2007-10-19 at 15:05 +0200, tahoma@xxxxxx wrote: > > Adding RTLD_GLOBAL to dlopen flags solves the problem for now. I have to > > investigate further. I stumbled across this behaviour while creating C++ > > Wrappers for Python with Swig. The order of importing the generated wrapper > > libraries results in different result. Exceptions thrown in C++ will be > > caught one time the other time not. So I stripped down the generated wrapper > > code and tried to emulate Python's import. I do not know whether Python uses > > RTLD_GLOBAL when importing libraries or not. > > Sorry for bothering you with this problem. > The RTLD_GLOBAL hint was very helpful and helped me to > solve this problem with my wrappers. One has to set this > flag for Python as well because it uses RTLD_LOCAL as default. > > Thanks for pointing me into the right direction, I think this is a 'bug' in the code: you should NOT use RTLD_GLOBAL. The correct flags are RTLD_NOW | RTLD_LOCAL. What you MUST do is make sure all the methods of exception E are declared but not defined in the header file, including copy constructor and assignment operator even if they're private and not to be used. In other words, make sure the compiler does NOT generate any methods, and make sure no method implementations are inline or otherwise visible. This should ensure the rtti/vtables go in the library X you want (this isn't guaranteed, but most compilers lay down vtables/rtti with side the first method, constructor, or destructor defined, possibly in several object files, but never if only the class definition is seen .. otherwise dynamic linkage would create duplicate vtables/rttis. Duplicate rtti causes the problem you have encountered). If you dlopen(), you should NOT allow any symbols to leak into the symbol table! And you should NOT allow any undefined symbols in the library to be bound against the global symbol table either, just because they happen to be there. The plugin library must be linked against the libraries that contain the definitions of symbols it requires, and so must every other library AND the application (excluding dlsym()bols of course). Since you cannot dlsym() a type, this correctly ensures you CANNOT catch an exception defined in a plugin. This cannot be permitted. (Except with ... or a shared base of course!) If you have a library L which throws E, then both L and the application A MUST be linked against X, the library containing the definition of E. You do it like: X (contains E) |\ | ------------------+ | | L (throws E) --dl---A (catches E) both L and A are *linked* against X. A dlopens L, and uses the flags: dlopen(.., RTLD_LOCAL | RTLD_NOW) There are a couple of exceptions to this rule, due to bad design of C and C++: if you need to do malloc() or operator new() replacement cruft, then you may need to use some linker trickery to work around the faulty design. The bottom line is that symbol sharing must be by design: you either share a separate library between 2 clients using static/load time linkage OR you use dlopen and dynamic/indirect linkage. You should never do both at the same time (from the one client). If you dlopen, the ONLY symbols you should be able to get are with dlsym (unless you happen to also link against it, which is possible but unusual). -- John Skaller <skaller at users dot sf dot net> Felix, successor to C++: http://felix.sf.net