From 3414c56b6c7c521d868c9a137ca2ace2e26b5b2e Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 21 Oct 2023 19:50:14 +0200 Subject: [PATCH 1/2] Workaround NVCC parse failure in `cast_op` (#4893) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Workaround NVCC parse failure in `cast_op` There is a bug in some CUDA versions (observed in CUDA 12.1 and 11.7 w/ GCC 12.2), that makes `cast_op` fail to compile: `cast.h:45:120: error: expected template-name before ‘<’ token` Defining the nested type as an alias and using it allows this to work without any change in semantics. Fixes #4606 * style: pre-commit fixes * Add comments to result_t referencing PR --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- include/pybind11/cast.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 3c9b7c927..8b5beb0ef 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -42,13 +42,15 @@ using make_caster = type_caster>; // Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T template typename make_caster::template cast_op_type cast_op(make_caster &caster) { - return caster.operator typename make_caster::template cast_op_type(); + using result_t = typename make_caster::template cast_op_type; // See PR #4893 + return caster.operator result_t(); } template typename make_caster::template cast_op_type::type> cast_op(make_caster &&caster) { - return std::move(caster).operator typename make_caster:: - template cast_op_type::type>(); + using result_t = typename make_caster::template cast_op_type< + typename std::add_rvalue_reference::type>; // See PR #4893 + return std::move(caster).operator result_t(); } template From bf88e29c95d20a94528637c1827df757821b5a88 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 23 Oct 2023 12:51:04 -0700 Subject: [PATCH 2/2] Bug fix: Replace bare `static exception` with `gil_safe_call_once_and_store`. (#4897) This is to ensure that `Py_DECREF()` is not called after the Python interpreter was finalized already: https://github.com/pybind/pybind11/blob/3414c56b6c7c521d868c9a137ca2ace2e26b5b2e/include/pybind11/gil_safe_call_once.h#L19 --- include/pybind11/pybind11.h | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index a94f6f0f1..95f7fa2eb 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -14,6 +14,7 @@ #include "detail/init.h" #include "attr.h" #include "gil.h" +#include "gil_safe_call_once.h" #include "options.h" #include "typing.h" @@ -2609,23 +2610,14 @@ public: }; PYBIND11_NAMESPACE_BEGIN(detail) -// Returns a reference to a function-local static exception object used in the simple -// register_exception approach below. (It would be simpler to have the static local variable -// directly in register_exception, but that makes clang <3.5 segfault - issue #1349). -template -exception &get_exception_object() { - static exception ex; - return ex; -} // Helper function for register_exception and register_local_exception template exception & register_exception_impl(handle scope, const char *name, handle base, bool isLocal) { - auto &ex = detail::get_exception_object(); - if (!ex) { - ex = exception(scope, name, base); - } + PYBIND11_CONSTINIT static gil_safe_call_once_and_store> exc_storage; + exc_storage.call_once_and_store_result( + [&]() { return exception(scope, name, base); }); auto register_func = isLocal ? ®ister_local_exception_translator : ®ister_exception_translator; @@ -2637,10 +2629,10 @@ register_exception_impl(handle scope, const char *name, handle base, bool isLoca try { std::rethrow_exception(p); } catch (const CppException &e) { - set_error(detail::get_exception_object(), e.what()); + set_error(exc_storage.get_stored(), e.what()); } }); - return ex; + return exc_storage.get_stored(); } PYBIND11_NAMESPACE_END(detail)