[C++-sig] question on boost.python exception mechanisms

Holger Joukl Holger.Joukl at LBBW.de
Wed Apr 17 10:29:08 CEST 2013


Hi,

Giuseppe Corbelli <giuseppe.corbelli at copanitalia.com> wrote on 09.04.2013
09:09:14:

> On 08/04/2013 14:11, Holger Joukl wrote:
> >> I have found a couple of references.
> >> http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html (see
static-libgcc)
> >> http://gcc.gnu.org/wiki/Visibility
> >
> > Thanks, I'll need to look into these.
> >
> >> The proprietary lib is shared, right? linked to? shared? static?
> >
> > Shared C lib, we compile a shared C++ lib linked to the C lib from the
> > vendor
> > C++ sources, which we shared-link the (shared) Boost.Python wrapper to.
>
> Quoting from the manual:
> There are several situations in which an application should use the
shared
> libgcc instead of the static version. The most common of these is when
the
> application wishes to throw and catch exceptions across different shared
> libraries. In that case, each of the libraries as well as the application

> itself should use the shared libgcc.

Both the shared libboost_python.so and the extension module I'm building
link against
the shared libgcc_s.so.

> However, if a library or main executable is supposed to throw or catch
> exceptions, you must link it using the G++ or GCJ driver, as appropriate
for
> the languages used in the program, or using the option -shared-libgcc,
such
> that it is linked with the shared libgcc.
>
> Likely the C_lib.so is not linked to libgcc_s.so. Don't know if
it'spossible
> to "extract" the objects from the shared .so. Maybe playing dirty
> with LD_PRELOAD?

While the shared lib is indeed not linked to libgcc_s.so I now don't think
this does
make any difference for the problem at hand:

Experimenting with this simple test lib:

0 $ cat dispatch.h
// File: dispatch.h

#ifdef __cplusplus
extern "C" {
#endif


typedef char const *cb_arg_t;
typedef void (*callback_func_ptr_t)(cb_arg_t);

void invoke(callback_func_ptr_t cb, cb_arg_t arg);


#ifdef __cplusplus
}
#endif



0  $ cat dispatch.c
// File: dispatch.c

#include <stdio.h>
#include "dispatch.h"

void invoke(callback_func_ptr_t cb, cb_arg_t arg) {
    printf("--> invoke(%d, %s)\n", &(*cb), arg);
    (*cb)(arg);
    printf("<-- invoke(%d, %s)\n", &(*cb), arg);
}

$ cat dispatch_main.cpp
// File: dispatch_main.cpp

#include <iostream>
#include <stdexcept>
#include "dispatch.h"

void callback(cb_arg_t arg) {
    printf("--> CPP callback(%s)\n", arg);
    printf("<-- CPP callback(%s)\n", arg);
}


void callback_with_exception(cb_arg_t arg) {
    printf("--> CPP exception-throwing callback(%s)\n", arg);
    throw std::runtime_error("throwing up");
    printf("<-- CPP exception-throwing callback(%s)\n", arg);
}


int main(void) {
    std::cout << "--> CPP main" << std::endl;
    cb_arg_t s = "CPP main callback argument";
    invoke(&callback, s);
    try {
        invoke(&callback_with_exception, s);
    } catch (const std::exception& exc) {
        std::cout << "caught callback exception: " << exc.what() <<
std::endl;
    }
    std::cout << "<-- CPP main" << std::endl;
    return 0;
}

I've found that:
(1) linking the C lib dynamically or statically against libgcc does not
make any difference wrt exception segfaulting.

I.e. lib compiled with
 - gcc -static-libgcc -o libdispatch.so -shared -fPIC dispatch.c:
    $ ldd libdispatch.so
        libc.so.1 =>     /lib/libc.so.1
        libm.so.2 =>     /lib/libm.so.2
        /platform/SUNW,Sun-Fire-V490/lib/libc_psr.so.1
 - gcc -o libdispatch.so -shared -fPIC dispatch.c
    $ ldd libdispatch.so
        libgcc_s.so.1 =>         /usr/lib/libgcc_s.so.1
        libc.so.1 =>     /lib/libc.so.1
        libm.so.2 =>     /lib/libm.so.2
        /platform/SUNW,Sun-Fire-V490/lib/libc_psr.so.1

will not make any difference when running the main program:
0 $ g++ -I. -L. -R. -ldispatch dispatch_main.cpp
0 $ ./a.out
--> CPP main
--> invoke(68316, CPP main callback argument)
--> CPP callback(CPP main callback argument)
<-- CPP callback(CPP main callback argument)
<-- invoke(68316, CPP main callback argument)
--> invoke(68372, CPP main callback argument)
--> CPP exception-throwing callback(CPP main callback argument)
terminate called after throwing an instance of 'std::runtime_error'
  what():  throwing up
Abort (core dumped)

(2) Compiling the C lib with exception support i.e. -fexceptions will make
the segfault disappear:

0 $ gcc -static-libgcc -fexceptions -o libdispatch.so -shared -fPIC
dispatch.c
0 $ ./a.out
--> CPP main
--> invoke(68720, CPP main callback argument)
--> CPP callback(CPP main callback argument)
<-- CPP callback(CPP main callback argument)
<-- invoke(68720, CPP main callback argument)
--> invoke(68776, CPP main callback argument)
--> CPP exception-throwing callback(CPP main callback argument)
caught callback exception: throwing up
<-- CPP main
0 $ ldd libdispatch.so
        libc.so.1 =>     /lib/libc.so.1
        libm.so.2 =>     /lib/libm.so.2
        /platform/SUNW,Sun-Fire-V490/lib/libc_psr.so.1
0 $ gcc -fexceptions -o libdispatch.so -shared -fPIC dispatch.c
0 $ ./a.out
--> CPP main
--> invoke(68720, CPP main callback argument)
--> CPP callback(CPP main callback argument)
<-- CPP callback(CPP main callback argument)
<-- invoke(68720, CPP main callback argument)
--> invoke(68776, CPP main callback argument)
--> CPP exception-throwing callback(CPP main callback argument)
caught callback exception: throwing up
<-- CPP main
0 $ ldd libdispatch.so
        libgcc_s.so.1 =>         /usr/lib/libgcc_s.so.1
        libc.so.1 =>     /lib/libc.so.1
        libm.so.2 =>     /lib/libm.so.2
        /platform/SUNW,Sun-Fire-V490/lib/libc_psr.so.1

So, wrapping up, it looks like if the C lib isn't compiled with exception
support there is
no way that an exception can propagate through the C parts without
segfaulting, regardless of linking
dynamically or statically against libgcc.
>From the cited gcc documentation I understand that linking dynamically or
statically will
however influence your capabilities on throwing in *one* shared lib and
catching in *another* shared lib,
all participating libraries *compiled with exception support*, though.

Which means I'll need to do something along the lines that Niall sketched
out.

Thanks,
Holger

Landesbank Baden-Wuerttemberg
Anstalt des oeffentlichen Rechts
Hauptsitze: Stuttgart, Karlsruhe, Mannheim, Mainz
HRA 12704
Amtsgericht Stuttgart



More information about the Cplusplus-sig mailing list