mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
demo race when using call_guard<gil_scoped_release> and implicitly_convertible
This commit is contained in:
parent
028812ae7e
commit
5f3d8d806a
@ -97,5 +97,31 @@ TEST_SUBMODULE(call_policies, m) {
|
|||||||
|
|
||||||
m.def("with_gil", report_gil_status);
|
m.def("with_gil", report_gil_status);
|
||||||
m.def("without_gil", report_gil_status, py::call_guard<py::gil_scoped_release>());
|
m.def("without_gil", report_gil_status, py::call_guard<py::gil_scoped_release>());
|
||||||
|
|
||||||
|
class MyInt {
|
||||||
|
public:
|
||||||
|
MyInt(int i)
|
||||||
|
: i_(i)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int i_;
|
||||||
|
};
|
||||||
|
py::class_<MyInt>(m, "MyInt")
|
||||||
|
.def(py::init<int>());
|
||||||
|
py::implicitly_convertible<int, MyInt>();
|
||||||
|
|
||||||
|
// This function races
|
||||||
|
m.def("guard_without_gil_implicit_conversion",
|
||||||
|
[](MyInt my_int) {
|
||||||
|
return my_int.i_;
|
||||||
|
},
|
||||||
|
py::call_guard<py::gil_scoped_release>());
|
||||||
|
|
||||||
|
// This function works fine
|
||||||
|
m.def("without_gil_implicit_conversion",
|
||||||
|
[](MyInt my_int) {
|
||||||
|
py::gil_scoped_release gil_release;
|
||||||
|
return my_int.i_;
|
||||||
|
});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import pytest
|
import pytest
|
||||||
|
import threading
|
||||||
|
|
||||||
import env # noqa: F401
|
import env # noqa: F401
|
||||||
|
|
||||||
@ -217,3 +218,33 @@ def test_call_guard():
|
|||||||
if hasattr(m, "with_gil"):
|
if hasattr(m, "with_gil"):
|
||||||
assert m.with_gil() == "GIL held"
|
assert m.with_gil() == "GIL held"
|
||||||
assert m.without_gil() == "GIL released"
|
assert m.without_gil() == "GIL released"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"test_func",
|
||||||
|
["guard_without_gil_implicit_conversion", "without_gil_implicit_conversion"],
|
||||||
|
)
|
||||||
|
def test_without_gil_implicit_conversion(test_func):
|
||||||
|
try:
|
||||||
|
func = getattr(m, test_func)
|
||||||
|
except AttributeError:
|
||||||
|
return
|
||||||
|
|
||||||
|
num_threads = 16
|
||||||
|
|
||||||
|
def check(results, i):
|
||||||
|
results[i] = func(42) == 42
|
||||||
|
|
||||||
|
results = [None] * num_threads
|
||||||
|
for _ in range(int(1e4)):
|
||||||
|
threads = []
|
||||||
|
for i in range(num_threads):
|
||||||
|
thread = threading.Thread(target=check, args=(results, i))
|
||||||
|
thread.start()
|
||||||
|
threads.append(thread)
|
||||||
|
for thread in threads:
|
||||||
|
thread.join()
|
||||||
|
|
||||||
|
ok = all(results)
|
||||||
|
if not ok:
|
||||||
|
raise AssertionError(results)
|
||||||
|
Loading…
Reference in New Issue
Block a user