From 42455b5e1de4669d85fe3ca00ba59ca75f6ff64e Mon Sep 17 00:00:00 2001 From: StarQTius <73899717+StarQTius@users.noreply.github.com> Date: Sun, 20 Feb 2022 17:00:29 +0100 Subject: [PATCH] fix: clear local internals after finalizing interpreter #2101 (#3744) * Clear local internals after finalizing interpreter * Add descriptive comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- include/pybind11/embed.h | 4 ++++ tests/test_embed/test_interpreter.cpp | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/pybind11/embed.h b/include/pybind11/embed.h index 84e442221..683f24280 100644 --- a/include/pybind11/embed.h +++ b/include/pybind11/embed.h @@ -247,6 +247,10 @@ inline void finalize_interpreter() { if (builtins.contains(id) && isinstance(builtins[id])) { internals_ptr_ptr = capsule(builtins[id]); } + // Local internals contains data managed by the current interpreter, so we must clear them to + // avoid undefined behaviors when initializing another interpreter + detail::get_local_internals().registered_types_cpp.clear(); + detail::get_local_internals().registered_exception_translators.clear(); Py_Finalize(); diff --git a/tests/test_embed/test_interpreter.cpp b/tests/test_embed/test_interpreter.cpp index 5782bda61..05c66ba99 100644 --- a/tests/test_embed/test_interpreter.cpp +++ b/tests/test_embed/test_interpreter.cpp @@ -380,3 +380,21 @@ TEST_CASE("sys.argv gets initialized properly") { } py::initialize_interpreter(); } + +TEST_CASE("make_iterator can be called before then after finalizing an interpreter") { + // Reproduction of issue #2101 (https://github.com/pybind/pybind11/issues/2101) + py::finalize_interpreter(); + + std::vector container; + { + pybind11::scoped_interpreter g; + auto iter = pybind11::make_iterator(container.begin(), container.end()); + } + + REQUIRE_NOTHROW([&]() { + pybind11::scoped_interpreter g; + auto iter = pybind11::make_iterator(container.begin(), container.end()); + }()); + + py::initialize_interpreter(); +}