diff --git a/cuda_core/cuda/core/_cpp/resource_handles.cpp b/cuda_core/cuda/core/_cpp/resource_handles.cpp index 7692d34287..c17b2830de 100644 --- a/cuda_core/cuda/core/_cpp/resource_handles.cpp +++ b/cuda_core/cuda/core/_cpp/resource_handles.cpp @@ -77,19 +77,7 @@ NvJitLinkDestroyFn p_nvJitLinkDestroy = nullptr; namespace { -#if PY_VERSION_HEX < 0x030D0000 -extern "C" int _Py_IsFinalizing(void); -#endif - -inline bool py_is_finalizing() noexcept { -#if PY_VERSION_HEX >= 0x030D0000 - return Py_IsFinalizing(); -#else - // Python < 3.13 does not expose Py_IsFinalizing() publicly. Use the private - // API that exists in those versions. - return _Py_IsFinalizing() != 0; -#endif -} +using cuda_core::detail::py_is_finalizing; // Helper to release the GIL while calling into the CUDA driver. // This guard is *conditional*: if the caller already dropped the GIL, diff --git a/cuda_core/cuda/core/_cpp/resource_handles.hpp b/cuda_core/cuda/core/_cpp/resource_handles.hpp index 724d6e1bd9..2f9c19fe15 100644 --- a/cuda_core/cuda/core/_cpp/resource_handles.hpp +++ b/cuda_core/cuda/core/_cpp/resource_handles.hpp @@ -517,8 +517,24 @@ inline std::intptr_t as_intptr(const CuLinkHandle& h) noexcept { // as_py() - convert handle to Python wrapper object (returns new reference) namespace detail { + +#if PY_VERSION_HEX < 0x030D0000 +extern "C" int _Py_IsFinalizing(void); +#endif + +inline bool py_is_finalizing() noexcept { +#if PY_VERSION_HEX >= 0x030D0000 + return Py_IsFinalizing(); +#else + return _Py_IsFinalizing() != 0; +#endif +} + // n.b. class lookup is not cached to avoid deadlock hazard, see DESIGN.md inline PyObject* make_py(const char* module_name, const char* class_name, std::intptr_t value) noexcept { + if (py_is_finalizing()) { + Py_RETURN_NONE; + } PyObject* mod = PyImport_ImportModule(module_name); if (!mod) return nullptr; PyObject* cls = PyObject_GetAttrString(mod, class_name);