From 686ec79d50f5c655d8e91b9b45ca29bf4d66e47b Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 16 Jan 2024 14:37:35 -0800 Subject: [PATCH] Add test_class_release_gil_before_calling_cpp_dtor --- tests/CMakeLists.txt | 1 + ...ss_release_gil_before_calling_cpp_dtor.cpp | 51 +++++++++++++++++++ ...ass_release_gil_before_calling_cpp_dtor.py | 19 +++++++ 3 files changed, 71 insertions(+) create mode 100644 tests/test_class_release_gil_before_calling_cpp_dtor.cpp create mode 100644 tests/test_class_release_gil_before_calling_cpp_dtor.py diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c55b0f2f..91cd230b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -119,6 +119,7 @@ set(PYBIND11_TEST_FILES test_callbacks test_chrono test_class + test_class_release_gil_before_calling_cpp_dtor test_class_sh_basic test_class_sh_disowning test_class_sh_disowning_mi diff --git a/tests/test_class_release_gil_before_calling_cpp_dtor.cpp b/tests/test_class_release_gil_before_calling_cpp_dtor.cpp new file mode 100644 index 00000000..f0460bfd --- /dev/null +++ b/tests/test_class_release_gil_before_calling_cpp_dtor.cpp @@ -0,0 +1,51 @@ +#include + +#include "pybind11_tests.h" + +#include +#include + +namespace pybind11_tests { +namespace class_release_gil_before_calling_cpp_dtor { + +using RegistryType = std::unordered_map; + +RegistryType &PyGILState_Check_Results() { + static auto *singleton = new RegistryType(); + return *singleton; +} + +template // Using int as a trick to easily generate a series of types. +struct ProbeType { +private: + std::string unique_key; + +public: + explicit ProbeType(const std::string &unique_key) : unique_key{unique_key} {} + + ~ProbeType() { + RegistryType ® = PyGILState_Check_Results(); + assert(reg.count(unique_key) == 0); + reg[unique_key] = PyGILState_Check(); + } +}; + +} // namespace class_release_gil_before_calling_cpp_dtor +} // namespace pybind11_tests + +TEST_SUBMODULE(class_release_gil_before_calling_cpp_dtor, m) { + using namespace pybind11_tests::class_release_gil_before_calling_cpp_dtor; + + py::class_>(m, "ProbeType0").def(py::init()); + + py::class_>(m, "ProbeType1", py::release_gil_before_calling_cpp_dtor()) + .def(py::init()); + + m.def("GetPyGILState_Check_Result", [](const std::string &unique_key) -> std::string { + RegistryType ® = PyGILState_Check_Results(); + if (reg.count(unique_key) == 0) { + return "MISSING"; + } + return std::to_string(reg[unique_key]); + }); +} diff --git a/tests/test_class_release_gil_before_calling_cpp_dtor.py b/tests/test_class_release_gil_before_calling_cpp_dtor.py new file mode 100644 index 00000000..1b4b7044 --- /dev/null +++ b/tests/test_class_release_gil_before_calling_cpp_dtor.py @@ -0,0 +1,19 @@ +import gc + +import pytest + +from pybind11_tests import class_release_gil_before_calling_cpp_dtor as m + + +@pytest.mark.parametrize( + ("probe_type", "unique_key", "expected_result"), + [ + (m.ProbeType0, "without_manipulating_gil", "1"), + (m.ProbeType1, "release_gil_before_calling_cpp_dtor", "0"), + ], +) +def test_gil_state_check_results(probe_type, unique_key, expected_result): + probe_type(unique_key) + gc.collect() + result = m.GetPyGILState_Check_Result(unique_key) + assert result == expected_result