Skip to content

Commit 686ec79

Browse files
committed
Add test_class_release_gil_before_calling_cpp_dtor
1 parent d7a9411 commit 686ec79

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ set(PYBIND11_TEST_FILES
119119
test_callbacks
120120
test_chrono
121121
test_class
122+
test_class_release_gil_before_calling_cpp_dtor
122123
test_class_sh_basic
123124
test_class_sh_disowning
124125
test_class_sh_disowning_mi
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <pybind11/pybind11.h>
2+
3+
#include "pybind11_tests.h"
4+
5+
#include <string>
6+
#include <unordered_map>
7+
8+
namespace pybind11_tests {
9+
namespace class_release_gil_before_calling_cpp_dtor {
10+
11+
using RegistryType = std::unordered_map<std::string, int>;
12+
13+
RegistryType &PyGILState_Check_Results() {
14+
static auto *singleton = new RegistryType();
15+
return *singleton;
16+
}
17+
18+
template <int> // Using int as a trick to easily generate a series of types.
19+
struct ProbeType {
20+
private:
21+
std::string unique_key;
22+
23+
public:
24+
explicit ProbeType(const std::string &unique_key) : unique_key{unique_key} {}
25+
26+
~ProbeType() {
27+
RegistryType &reg = PyGILState_Check_Results();
28+
assert(reg.count(unique_key) == 0);
29+
reg[unique_key] = PyGILState_Check();
30+
}
31+
};
32+
33+
} // namespace class_release_gil_before_calling_cpp_dtor
34+
} // namespace pybind11_tests
35+
36+
TEST_SUBMODULE(class_release_gil_before_calling_cpp_dtor, m) {
37+
using namespace pybind11_tests::class_release_gil_before_calling_cpp_dtor;
38+
39+
py::class_<ProbeType<0>>(m, "ProbeType0").def(py::init<std::string>());
40+
41+
py::class_<ProbeType<1>>(m, "ProbeType1", py::release_gil_before_calling_cpp_dtor())
42+
.def(py::init<std::string>());
43+
44+
m.def("GetPyGILState_Check_Result", [](const std::string &unique_key) -> std::string {
45+
RegistryType &reg = PyGILState_Check_Results();
46+
if (reg.count(unique_key) == 0) {
47+
return "MISSING";
48+
}
49+
return std::to_string(reg[unique_key]);
50+
});
51+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import gc
2+
3+
import pytest
4+
5+
from pybind11_tests import class_release_gil_before_calling_cpp_dtor as m
6+
7+
8+
@pytest.mark.parametrize(
9+
("probe_type", "unique_key", "expected_result"),
10+
[
11+
(m.ProbeType0, "without_manipulating_gil", "1"),
12+
(m.ProbeType1, "release_gil_before_calling_cpp_dtor", "0"),
13+
],
14+
)
15+
def test_gil_state_check_results(probe_type, unique_key, expected_result):
16+
probe_type(unique_key)
17+
gc.collect()
18+
result = m.GetPyGILState_Check_Result(unique_key)
19+
assert result == expected_result

0 commit comments

Comments
 (0)