pybind / pybind/pybind11

register_exception does not work after re-initializing an embedded interpreter

Open
#1,610 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
18k
Forks
2.3k
Avg merge
5d 17h
Merged PRs (30d)
10

Description

Consider the following example, which adds an exception type SomeException to module foo , re-initializes the interpreter, and tries to do the same again:

PYBIND11_EMBEDDED_MODULE(foo, mod) { /* Nothing */ }

struct SomeException : public std::runtime_error {};

int main() {

    {
        pybind11::scoped_interpreter interpreter;
        auto foo = pybind11::module::import("foo");
        pybind11::register_exception<SomeException>(foo, "SomeException");
        assert(!foo.attr("SomeException").is_none());
    }

    {
        pybind11::scoped_interpreter interpreter;
        auto foo = pybind11::module::import("foo");
        pybind11::register_exception<SomeException>(foo, "SomeException");
        assert(!foo.attr("SomeException").is_none()); // This throws an exception
    }

}

The second call to register_exception fails silently, because the first pybind11::exception object is still alive due to its static lifetime in pybind11::detail::get_exception_object, making register_exception think that the type has already been added.

The same behavior can be observed when trying to add the same exception type to multiple modules:

PYBIND11_EMBEDDED_MODULE(foo, mod) { /* Nothing */ }
PYBIND11_EMBEDDED_MODULE(bar, mod) { /* Nothing */ }

struct SomeException : public std::runtime_error {};

int main() {
    pybind11::scoped_interpreter interpreter;
    auto foo = pybind11::module::import("foo");
    pybind11::register_exception<SomeException>(foo, "SomeException");
    pybind11::register_exception<SomeException>(bar, "SomeException");
    assert(!foo.attr("SomeException").is_none());
    assert(!bar.attr("SomeException").is_none()); // This throws an exception
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in include/pybind11/pybind11.h at detail::get_exception_object, which the issue identifies as retaining the exception object across interpreter lifetimes. Reproduce the examples for interpreter re-initialization and registration in multiple modules; done means both calls expose SomeException without throwing or silently failing.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.