From 8c62dad4f505c5620e3fbbff9feca8225b0302e1 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 24 Oct 2022 12:22:29 -0700 Subject: [PATCH 1/8] Empty *cross_module_exception_odr_* files, to be filled in. --- tests/cross_module_exception_odr_1.cpp | 3 +++ tests/cross_module_exception_odr_2.cpp | 3 +++ tests/test_cross_module_exception_odr_1.py | 5 +++++ tests/test_cross_module_exception_odr_2.py | 5 +++++ 4 files changed, 16 insertions(+) create mode 100644 tests/cross_module_exception_odr_1.cpp create mode 100644 tests/cross_module_exception_odr_2.cpp create mode 100644 tests/test_cross_module_exception_odr_1.py create mode 100644 tests/test_cross_module_exception_odr_2.py diff --git a/tests/cross_module_exception_odr_1.cpp b/tests/cross_module_exception_odr_1.cpp new file mode 100644 index 0000000000..35f4fd51c5 --- /dev/null +++ b/tests/cross_module_exception_odr_1.cpp @@ -0,0 +1,3 @@ +#include "pybind11/pybind11.h" + +PYBIND11_MODULE(cross_module_exception_odr_1, m) { m.attr("foo") = 1; } diff --git a/tests/cross_module_exception_odr_2.cpp b/tests/cross_module_exception_odr_2.cpp new file mode 100644 index 0000000000..9fd3bdfe49 --- /dev/null +++ b/tests/cross_module_exception_odr_2.cpp @@ -0,0 +1,3 @@ +#include "pybind11/pybind11.h" + +PYBIND11_MODULE(cross_module_exception_odr_2, m) { m.attr("foo") = 2; } diff --git a/tests/test_cross_module_exception_odr_1.py b/tests/test_cross_module_exception_odr_1.py new file mode 100644 index 0000000000..db22728d33 --- /dev/null +++ b/tests/test_cross_module_exception_odr_1.py @@ -0,0 +1,5 @@ +import cross_module_exception_odr_1 as m + + +def test_foo(): + assert m.foo == 1 diff --git a/tests/test_cross_module_exception_odr_2.py b/tests/test_cross_module_exception_odr_2.py new file mode 100644 index 0000000000..4588323f9d --- /dev/null +++ b/tests/test_cross_module_exception_odr_2.py @@ -0,0 +1,5 @@ +import cross_module_exception_odr_2 as m + + +def test_foo(): + assert m.foo == 2 From c35451fcf3e428a400e7d2ed50a41f57efcb68eb Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 24 Oct 2022 12:56:57 -0700 Subject: [PATCH 2/8] This passes local testing. --- tests/cross_module_exception_odr_1.cpp | 28 +++++++++++++++++++++- tests/cross_module_exception_odr_2.cpp | 28 +++++++++++++++++++++- tests/test_cross_module_exception_odr_1.py | 6 +++-- tests/test_cross_module_exception_odr_2.py | 6 +++-- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/tests/cross_module_exception_odr_1.cpp b/tests/cross_module_exception_odr_1.cpp index 35f4fd51c5..d2dae98d35 100644 --- a/tests/cross_module_exception_odr_1.cpp +++ b/tests/cross_module_exception_odr_1.cpp @@ -1,3 +1,29 @@ #include "pybind11/pybind11.h" -PYBIND11_MODULE(cross_module_exception_odr_1, m) { m.attr("foo") = 1; } +#include + +namespace cross_module_exception_odr { + +class PYBIND11_EXPORT_EXCEPTION evolving : public std::exception { +public: + const char *what() const noexcept override { return "v1"; } +}; + +} // namespace cross_module_exception_odr + +PYBIND11_MODULE(cross_module_exception_odr_1, m) { + using namespace cross_module_exception_odr; + namespace py = pybind11; + + py::register_exception_translator([](std::exception_ptr p) { + try { + if (p) { + std::rethrow_exception(p); + } + } catch (const evolving &e) { + PyErr_SetString(PyExc_RuntimeError, e.what()); + } + }); + + m.def("raise_evolving", []() { throw evolving(); }); +} diff --git a/tests/cross_module_exception_odr_2.cpp b/tests/cross_module_exception_odr_2.cpp index 9fd3bdfe49..98cda07b6c 100644 --- a/tests/cross_module_exception_odr_2.cpp +++ b/tests/cross_module_exception_odr_2.cpp @@ -1,3 +1,29 @@ #include "pybind11/pybind11.h" -PYBIND11_MODULE(cross_module_exception_odr_2, m) { m.attr("foo") = 2; } +#include + +namespace cross_module_exception_odr { + +class PYBIND11_EXPORT_EXCEPTION evolving : public std::exception { +public: + const char *what() const noexcept override { return "v2"; } +}; + +} // namespace cross_module_exception_odr + +PYBIND11_MODULE(cross_module_exception_odr_2, m) { + using namespace cross_module_exception_odr; + namespace py = pybind11; + + py::register_exception_translator([](std::exception_ptr p) { + try { + if (p) { + std::rethrow_exception(p); + } + } catch (const evolving &e) { + PyErr_SetString(PyExc_RuntimeError, e.what()); + } + }); + + m.def("raise_evolving", []() { throw evolving(); }); +} diff --git a/tests/test_cross_module_exception_odr_1.py b/tests/test_cross_module_exception_odr_1.py index db22728d33..e7d21a5598 100644 --- a/tests/test_cross_module_exception_odr_1.py +++ b/tests/test_cross_module_exception_odr_1.py @@ -1,5 +1,7 @@ import cross_module_exception_odr_1 as m +import pytest -def test_foo(): - assert m.foo == 1 +def test_raise_evolving(): + with pytest.raises(RuntimeError, match="v1"): + m.raise_evolving() diff --git a/tests/test_cross_module_exception_odr_2.py b/tests/test_cross_module_exception_odr_2.py index 4588323f9d..36cdd9340f 100644 --- a/tests/test_cross_module_exception_odr_2.py +++ b/tests/test_cross_module_exception_odr_2.py @@ -1,5 +1,7 @@ import cross_module_exception_odr_2 as m +import pytest -def test_foo(): - assert m.foo == 2 +def test_raise_evolving(): + with pytest.raises(RuntimeError, match="v2"): + m.raise_evolving() From 7a8612d0ae05a5f8700b18e43dc2888bb2f69961 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 24 Oct 2022 13:03:24 -0700 Subject: [PATCH 3/8] This still passes local testing. --- tests/cross_module_exception_odr_1.cpp | 6 +++--- tests/test_cross_module_exception_odr_1.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/cross_module_exception_odr_1.cpp b/tests/cross_module_exception_odr_1.cpp index d2dae98d35..a99ee47a4e 100644 --- a/tests/cross_module_exception_odr_1.cpp +++ b/tests/cross_module_exception_odr_1.cpp @@ -4,9 +4,9 @@ namespace cross_module_exception_odr { -class PYBIND11_EXPORT_EXCEPTION evolving : public std::exception { +class PYBIND11_EXPORT_EXCEPTION evolving : public std::runtime_error { public: - const char *what() const noexcept override { return "v1"; } + evolving(const std::string &msg) : std::runtime_error("v1:" + msg) {} }; } // namespace cross_module_exception_odr @@ -25,5 +25,5 @@ PYBIND11_MODULE(cross_module_exception_odr_1, m) { } }); - m.def("raise_evolving", []() { throw evolving(); }); + m.def("raise_evolving", [](const std::string &msg) { throw evolving(msg); }); } diff --git a/tests/test_cross_module_exception_odr_1.py b/tests/test_cross_module_exception_odr_1.py index e7d21a5598..c3cb526b15 100644 --- a/tests/test_cross_module_exception_odr_1.py +++ b/tests/test_cross_module_exception_odr_1.py @@ -3,5 +3,5 @@ def test_raise_evolving(): - with pytest.raises(RuntimeError, match="v1"): - m.raise_evolving() + with pytest.raises(RuntimeError, match="v1:t1"): + m.raise_evolving("t1") From 419bc326d0c73784c28ced8cc095bb47c6a4b191 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 24 Oct 2022 13:45:46 -0700 Subject: [PATCH 4/8] This still passes local testing (with clang 14 and gcc 12). --- tests/cross_module_exception_odr_1.cpp | 4 ++++ tests/cross_module_exception_odr_2.cpp | 6 ++++++ tests/test_cross_module_exception_odr_1.py | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/tests/cross_module_exception_odr_1.cpp b/tests/cross_module_exception_odr_1.cpp index a99ee47a4e..fe450e0c9a 100644 --- a/tests/cross_module_exception_odr_1.cpp +++ b/tests/cross_module_exception_odr_1.cpp @@ -26,4 +26,8 @@ PYBIND11_MODULE(cross_module_exception_odr_1, m) { }); m.def("raise_evolving", [](const std::string &msg) { throw evolving(msg); }); + m.def("raise_evolving_from_module_2", [](const py::capsule &cap) { + auto f = reinterpret_cast(cap.get_pointer()); + f(); + }); } diff --git a/tests/cross_module_exception_odr_2.cpp b/tests/cross_module_exception_odr_2.cpp index 98cda07b6c..ddf7ec9ed2 100644 --- a/tests/cross_module_exception_odr_2.cpp +++ b/tests/cross_module_exception_odr_2.cpp @@ -9,6 +9,8 @@ class PYBIND11_EXPORT_EXCEPTION evolving : public std::exception { const char *what() const noexcept override { return "v2"; } }; +void raise_evolving_from_module_2() { throw evolving(); } + } // namespace cross_module_exception_odr PYBIND11_MODULE(cross_module_exception_odr_2, m) { @@ -26,4 +28,8 @@ PYBIND11_MODULE(cross_module_exception_odr_2, m) { }); m.def("raise_evolving", []() { throw evolving(); }); + m.def("get_raise_evolving_from_module_2_capsule", []() { + return py::capsule(reinterpret_cast(&raise_evolving_from_module_2), + "raise_evolving_from_module_2_function_pointer"); + }); } diff --git a/tests/test_cross_module_exception_odr_1.py b/tests/test_cross_module_exception_odr_1.py index c3cb526b15..7d4a674595 100644 --- a/tests/test_cross_module_exception_odr_1.py +++ b/tests/test_cross_module_exception_odr_1.py @@ -1,7 +1,14 @@ import cross_module_exception_odr_1 as m +import cross_module_exception_odr_2 as m2 import pytest def test_raise_evolving(): with pytest.raises(RuntimeError, match="v1:t1"): m.raise_evolving("t1") + + +def test_raise_evolving_from_module_2(): + cap = m2.get_raise_evolving_from_module_2_capsule() + with pytest.raises(RuntimeError, match="v2"): + m.raise_evolving_from_module_2(cap) From 44dc0faec180d9dfd72284e4fae87d9eecee9e39 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 24 Oct 2022 14:02:45 -0700 Subject: [PATCH 5/8] cmake additions --- tests/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 491f215cef..105869866e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -125,6 +125,8 @@ set(PYBIND11_TEST_FILES test_const_name test_constants_and_functions test_copy_move + test_cross_module_exception_odr_1.py + test_cross_module_exception_odr_2.py test_custom_type_casters test_custom_type_setup test_docstring_options @@ -219,6 +221,8 @@ tests_extra_targets("test_exceptions.py;test_local_bindings.py;test_stl.py;test_ # And add additional targets for other tests. tests_extra_targets("test_exceptions.py" "cross_module_interleaved_error_already_set") tests_extra_targets("test_gil_scoped.py" "cross_module_gil_utils") +tests_extra_targets("test_cross_module_exception_odr_1.py" "cross_module_exception_odr_1") +tests_extra_targets("test_cross_module_exception_odr_2.py" "cross_module_exception_odr_2") set(PYBIND11_EIGEN_REPO "https://gitlab.com/libeigen/eigen.git" From c9abf7917771446daee325684d781a21411773c1 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 24 Oct 2022 14:36:24 -0700 Subject: [PATCH 6/8] clang-tidy: explicit --- tests/cross_module_exception_odr_1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cross_module_exception_odr_1.cpp b/tests/cross_module_exception_odr_1.cpp index fe450e0c9a..309ffe62a3 100644 --- a/tests/cross_module_exception_odr_1.cpp +++ b/tests/cross_module_exception_odr_1.cpp @@ -6,7 +6,7 @@ namespace cross_module_exception_odr { class PYBIND11_EXPORT_EXCEPTION evolving : public std::runtime_error { public: - evolving(const std::string &msg) : std::runtime_error("v1:" + msg) {} + explicit evolving(const std::string &msg) : std::runtime_error("v1:" + msg) {} }; } // namespace cross_module_exception_odr From f381a345ecaacf033c4f64c1a37415ecd24f7fbe Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 24 Oct 2022 14:49:15 -0700 Subject: [PATCH 7/8] Add C4275 warning suppressions for _MSC_VER --- tests/cross_module_exception_odr_1.cpp | 9 +++++++++ tests/cross_module_exception_odr_2.cpp | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/tests/cross_module_exception_odr_1.cpp b/tests/cross_module_exception_odr_1.cpp index 309ffe62a3..7d95c5e54b 100644 --- a/tests/cross_module_exception_odr_1.cpp +++ b/tests/cross_module_exception_odr_1.cpp @@ -4,11 +4,20 @@ namespace cross_module_exception_odr { +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4275) +#endif + class PYBIND11_EXPORT_EXCEPTION evolving : public std::runtime_error { public: explicit evolving(const std::string &msg) : std::runtime_error("v1:" + msg) {} }; +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + } // namespace cross_module_exception_odr PYBIND11_MODULE(cross_module_exception_odr_1, m) { diff --git a/tests/cross_module_exception_odr_2.cpp b/tests/cross_module_exception_odr_2.cpp index ddf7ec9ed2..440b1f615e 100644 --- a/tests/cross_module_exception_odr_2.cpp +++ b/tests/cross_module_exception_odr_2.cpp @@ -4,11 +4,20 @@ namespace cross_module_exception_odr { +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4275) +#endif + class PYBIND11_EXPORT_EXCEPTION evolving : public std::exception { public: const char *what() const noexcept override { return "v2"; } }; +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + void raise_evolving_from_module_2() { throw evolving(); } } // namespace cross_module_exception_odr From 42c955452aea243de11c652608186e07e73cfc94 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 24 Oct 2022 20:45:17 -0700 Subject: [PATCH 8/8] linux, darwin: `sys.setdlopenflags(RTLD_GLOBAL | RTLD_NOW)` --- tests/conftest.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 02ce263afc..e53ba43570 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,6 +4,13 @@ Adds docstring and exceptions message sanitizers. """ +import sys + +if sys.platform == "linux": + sys.setdlopenflags(0x100 | 0x2) # RTLD_GLOBAL | RTLD_NOW +elif sys.platform == "darwin": + sys.setdlopenflags(0x8 | 0x2) # RTLD_GLOBAL | RTLD_NOW + import contextlib import difflib import gc