views:

372

answers:

1

I have a test program called ftest. It loads .so files that contain tests and runs the tests that it finds in there. One of these tests loads and runs a .so that contains a Postgres database driver for our O/RM.

When the Postgres driver throws an exception which is defined in that .so file (or one that it links to, but ftest does not link to) and is caught by the test framework the exception destructor triggers a segfault.

This segfault happens whenever the compiled exception is in a .so that has been dynamically loaded (using dload).

This sort of thing works fine in Windows which has the same architecture. We don't really want to restrict ourselves to only use exceptions that are from the core libraries -- add-ins should be free to create their own exception classes and have them handled normally.

The exceptions are sub-classes of std::exception. Sometimes the exceptions may be defined in libraries (such as libpqxx) which means that exceptions are sometimes out of our control too.

Exceptions are thrown using something like:

throw exception_class( exception_arguments );

And are caught using:

catch ( std::exception &e ) {
    // handler code
}

Is there some special compiler option needed to get this working? Do we need to switch to throw exceptions via throw new exception_class( args ) (we don't really want to do this)?

+5  A: 

Assuming your using gcc -

Append -Wl,-E when you build the executable calling dlload(). This exports all type info symbols from the executable, which should allow the RTTI (when catching the exception) to work properly.

VC++ uses string compares to match typeinfo, results in slower dynamic_cast<> etc but smaller binaries. g++ uses pointer compares.

I encountered the same problem when attempting to use pure virtual interfaces classes implemented in a run-time loaded .so.

There are a few articles relating to the subject floating around on the net as well.

hope that helps, Hayman.

Hayman
It's actually the destructor that has the problem not the catch. I wouldn't be surprised if it's the location of the virtual table though -- maybe the .so doesn't give read permission on the page the table is loaded into so the destructor can't be read. That's pure speculation though.I'll see if I can work out how to set those options via Boost.Build.
KayEss
-Wl,E doesn't appear to have made any difference :(
KayEss
Actually I think the -Wl,E did have an effect -- there was a second problem where the exceptions were also making the .so unload before the exception had completed. Fixing both of these means that we now get the exceptions working without segfaults. yay!
KayEss