1

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
Xiaofeng
  • 532
  • 7
  • 22
  • 2
    C++ exceptions don't necessarily propagate across C ABI stack frames, since the C++ exception stack unwinding code may fail if it comes across non-C++ frames that it doesn't know how to unwind and destruct the local objects. I don't know if there is an easy way (say a compiler flag or linker flag) to fix the problem. – Eljay Jul 29 '20 at 13:10
  • 1
    Please provide a [mre] – Alan Birtles Jul 29 '20 at 13:11
  • more stack trace could also help. – Serge Jul 29 '20 at 13:15
  • @Eljay the library is loaded by a C program. – Xiaofeng Jul 29 '20 at 13:20
  • 1
    @Eljay The way I understood the question, the exception is being throw and caught within the C++ library, not crossing any C stack frames. – cdhowie Jul 29 '20 at 13:24
  • @cdhowie Yes, the exception is caught within the C++ library. – Xiaofeng Jul 29 '20 at 13:26
  • Then it's not an exception handler stack unwinding issue. Could be an ODR issue. A [mcve] would be most helpful, including how the program and the shared library are compiled. – Eljay Jul 29 '20 at 13:28
  • Thanks all for the suggestion, I will try to write a minimal reproducible example. – Xiaofeng Jul 29 '20 at 13:54
  • You cannot call C++ from C, only the other way around. (Of course you can try, but it is UB.) – Lorinczy Zsigmond Jul 30 '20 at 03:52
  • @LorinczyZsigmond I don't think so, see https://isocpp.org/wiki/faq/mixing-c-and-cpp#call-cpp – Xiaofeng Jul 30 '20 at 06:04
  • It clearly states that the main-executable has to be compiled with C++ compiler. Edit: read this for further reference: https://yosefk.com/c++fqa/mixing.html – Lorinczy Zsigmond Jul 30 '20 at 07:17
  • 1
    @LorinczyZsigmond you are right, it works if I recompile the `main.c` with g++. – Xiaofeng Jul 30 '20 at 07:40
  • @LorinczyZsigmond but there must be better way to mix C and C++. If the `main` is compiled by others, then you cannot write plugin using C++. That's unacceptable. – Xiaofeng Jul 30 '20 at 07:57
  • I'm afraid that's a well known fact, there's no point in fighting it. – Lorinczy Zsigmond Jul 30 '20 at 09:14
  • https://stackoverflow.com/questions/413473/dlopen-on-library-with-static-member-that-throws-exception-in-constructor-resu – pi1ot Oct 13 '22 at 10:27

0 Answers0