Skip to content

[BUG] register_exception_translator have different behaviour when building with different STL. #2847

Closed
@oraluben

Description

@oraluben

Issue description

If I have a module a who have an exception translator and module b who throws an exception,
and import a, b in order in another python module.

With libstdc++, when b throws an error, it will be catched by the registered translator,
while with libc++, it won't.

Output1:

+ python -c 'import foo; foo.bar.thr()'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
RuntimeError

Output2:

+ python -c 'import foo; foo.bar.thr()'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
KeyError: ''

See below for detailed information.

Reproducible example code

This repro requires additional dependencies. I recommend you run it from a docker container (debian:buster has been verified to work).

Install dependencies

#!/bin/sh
set -ex

apt-get update

apt-get install -y -qq python-dev libc++1 libc++-dev pybind11-dev g++
ln -s /usr/lib/llvm-7/lib/libc++abi.so.1 /usr/lib/llvm-7/lib/libc++abi.so || true

Generate test files

#!/bin/sh
set -ex

cat > foo.h <<EOF
#include <stdexcept>

struct e : public std::runtime_error {
    explicit e(const char* what) :
        std::runtime_error(what) {
    }
};
EOF

cat > foo.cc <<EOF
#include <pybind11/pybind11.h>

#include "foo.h"

namespace py = pybind11;

PYBIND11_MODULE(_foo, m) {
    py::register_exception_translator([](std::exception_ptr p) {
        try {
            if (p) std::rethrow_exception(p);
        } catch (const e &_e) {
            PyErr_SetString(PyExc_KeyError, _e.what());
        }
    });
};
EOF

cat > bar.cc <<EOF
#include <pybind11/pybind11.h>

#include "foo.h"

void thr() {
    throw e{""};
}

namespace py = pybind11;

PYBIND11_MODULE(bar, m)
{
    m.def("thr", &thr);
}
EOF

cat > foo.py <<EOF
import _foo

import bar
EOF

Build and run

#!/bin/sh
set -ex

# https://libcxx.llvm.org/docs/UsingLibcxx.html

g++ -I/usr/include/pybind11/ -I/usr/include/python2.7 \
-nostdinc++ -I/usr/lib/llvm-7/include/c++/v1 \
-fPIC -fvisibility=hidden -flto -fno-fat-lto-objects -std=gnu++11 \
-o bar.o -c bar.cc

g++ -fPIC \
-nostdinc++ -I/usr/lib/llvm-7/include/c++/v1 \
-flto -shared \
-nodefaultlibs -L/usr/lib/llvm-7/lib -lc++ -lc++abi -lm -lc -lgcc_s -lgcc \
-o bar.so bar.o

g++ -I/usr/include/pybind11/ -I/usr/include/python2.7 \
-nostdinc++ -I/usr/lib/llvm-7/include/c++/v1 \
-fPIC -fvisibility=hidden -flto -fno-fat-lto-objects -std=gnu++11 \
-o _foo.o -c foo.cc

g++ -fPIC \
-nostdinc++ -I/usr/lib/llvm-7/include/c++/v1 \
-flto -shared \
-nodefaultlibs -L/usr/lib/llvm-7/lib -lc++ -lc++abi -lm -lc -lgcc_s -lgcc \
-o _foo.so _foo.o

python -c "import foo; foo.bar.thr()" || true


g++ -I/usr/include/pybind11/ -I/usr/include/python2.7 \
-fPIC -fvisibility=hidden -flto -fno-fat-lto-objects -std=gnu++11 \
-o bar.o -c bar.cc

g++ -fPIC \
-flto -shared \
-o bar.so bar.o

g++ -I/usr/include/pybind11/ -I/usr/include/python2.7 \
-fPIC -fvisibility=hidden -flto -fno-fat-lto-objects -std=gnu++11 \
-o _foo.o -c foo.cc

g++ -fPIC \
-flto -shared \
-o _foo.so _foo.o

python -c "import foo; foo.bar.thr()" || true

rm -rf *.o *.so

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions