try-catch cannot catch exception in a shared library load by dlopen

619 views Asked by At

The library which contains the try-catch block is load dynamically using dlopen, and the try-catch block is as simple as bellow:

try {
    throw "sth";
} catch (...) {}

The program that dynamically load the library abort complains:

terminate called after throwing an instance of ...
terminate called recursively

And the backtrace is:

(gdb) bt
#0  0xb6c1904c in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:66
#1  0xb6c1c690 in __GI_abort () at abort.c:90
#2  0xb64ef634 in __gnu_cxx::__verbose_terminate_handler () at ../../../../../gcc~linaro-4.8-2013.12/libstdc++-v3/libsupc++/vterminate.cc:50
#3  0xb64ed4d8 in __cxxabiv1::__terminate (handler=<optimized out>) at ../../../../../gcc~linaro-4.8-2013.12/libstdc++-v3/libsupc++/eh_terminate.cc:38
#4  0xb64ed500 in std::terminate () at ../../../../../gcc~linaro-4.8-2013.12/libstdc++-v3/libsupc++/eh_terminate.cc:48
#5  0xb64ed898 in __cxxabiv1::__cxa_rethrow () at ../../../../../gcc~linaro-4.8-2013.12/libstdc++-v3/libsupc++/eh_throw.cc:122
#6  0xb64ef640 in __gnu_cxx::__verbose_terminate_handler () at ../../../../../gcc~linaro-4.8-2013.12/libstdc++-v3/libsupc++/vterminate.cc:80
#7  0xb64ed4d8 in __cxxabiv1::__terminate (handler=<optimized out>) at ../../../../../gcc~linaro-4.8-2013.12/libstdc++-v3/libsupc++/eh_terminate.cc:38
#8  0xb64ed500 in std::terminate () at ../../../../../gcc~linaro-4.8-2013.12/libstdc++-v3/libsupc++/eh_terminate.cc:48
#9  0xb64ed83c in __cxxabiv1::__cxa_throw (obj=0x50ec50, tinfo=<optimized out>, dest=<optimized out>) at ../../../../../gcc~linaro-4.8-2013.12/libstdc++-v3/libsupc++/eh_throw.cc:84
#10 0xb52d105c in init () at xxx.cpp:287
#11 0xb6f628e4 in start_app (appname=0x19dc09 "xxx", app=0xb52f5b7c <xxx>) at app-core.c:605
#12 0xb6f63c60 in __app_install (appname=0x19dc09 "xxx", app=0xb52f5b7c <xxx>, library=0x19deb9 "libxxx.so", dlhandle=0x50e220) at app-core.c:1008
#13 0xb6f63efc in app_install_x (appname=0x19dc09 "xxx", library=0x19deb9 "libxxx.so") at app-core.c:1060
#14 0xb6f663ac in create (nn=0x19db40) at plugin-loader.c:55
#15 0xb6f624cc in start_stop_single_instance (appname=0xad60 "plugin", app=0x133b0 <app_plugin_loader>, start=1, nn=0x19db40) at app-core.c:513
#16 0xb6f6276c in start_stop_instances (appname=0xad60 "plugin", app=0x133b0 <app_plugin_loader>, start=1) at app-core.c:561
#17 0xb6f6294c in start_app (appname=0xad60 "plugin", app=0x133b0 <app_plugin_loader>) at app-core.c:615
#18 0xb6f63c60 in __app_install (appname=0xad60 "plugin", app=0x133b0 <app_plugin_loader>, library=0xb6fb2f7c "built-in", dlhandle=0xb6ffda60) at app-core.c:1008
#19 0xb6f63cfc in app_install (appname=0xad60 "plugin", app=0x133b0 <app_plugin_loader>) at app-core.c:1017
#20 0x0000a2e4 in main (argn=2, argv=0xbefffe54) at main.c:299

It works well if I compile and run as an executable program.

Any ideas to figure this out?

Thanks.

P.S.

The version of the compiler is:

$ arm-hisiv400-linux-g++ --version
real-arm-hisiv400-linux-g++ (Hisilicon_v400) 4.8.3 20131202 (prerelease)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

The compile flags for the library is:

-g -O2 -fPIC -DPIC -Wall -Wextra -Wno-unused-parameter

A reproducible example:

The hello.cc


extern "C" {

void hello() {
    try {
        throw "hello world";
    } catch (...) {}
}

}

compiled by:

arm-hisiv400-linux-g++ -c -g -O2 -Wall -Werror -fPIC hello.cc
arm-hisiv400-linux-g++ -fPIC -DPIC -shared  libunwind-arm.so libunwind.so -g -O2 hello.o -Wl,-soname -Wl,hello.so -o hello.so

Note the packed/linked libunwind-arm.so and libunwind.so, I finally find this is the problem.

These two libraries are introduced by a library required by my shared library, it works well after removing them.

And the main.c:

#include <dlfcn.h>

int main(int argc, char* argv[]) {
    void* handle = dlopen(argv[1], RTLD_GLOBAL | RTLD_NOW);
    if (handle == NULL)
        return 1;

    typedef void(*func)();
    func f = (func)dlsym(handle, "hello");
    if (f == NULL) {
        return 1;
    }

    f();

    return 0;
}

and compiled main.c:

arm-hisiv400-linux-gcc main.c -g -O2 -Wall -Werror -ldl -o hello
0

There are 0 answers