mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15:12 +00:00
Bugfix/Check actual value when deregistering pybind11 instance (#2252)
* Add tests demonstrating the problem with deregistering pybind11 instances * Fix deregistering of different pybind11 instance from internals Co-authored-by: Yannick Jadoul <yannick.jadoul@belgacom.net> Co-authored-by: Blistic <wots_wot@hotmail.com>
This commit is contained in:
parent
b9d00273ee
commit
2b6b98e28f
@ -258,7 +258,7 @@ inline bool deregister_instance_impl(void *ptr, instance *self) {
|
||||
auto ®istered_instances = get_internals().registered_instances;
|
||||
auto range = registered_instances.equal_range(ptr);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
if (Py_TYPE(self) == Py_TYPE(it->second)) {
|
||||
if (self == it->second) {
|
||||
registered_instances.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
@ -420,6 +420,16 @@ TEST_SUBMODULE(class_, m) {
|
||||
py::class_<PyPrintDestructor>(m, "PyPrintDestructor")
|
||||
.def(py::init<>())
|
||||
.def("throw_something", &PyPrintDestructor::throw_something);
|
||||
|
||||
struct SamePointer {};
|
||||
static SamePointer samePointer;
|
||||
py::class_<SamePointer, std::unique_ptr<SamePointer, py::nodelete>>(m, "SamePointer")
|
||||
.def(py::init([]() { return &samePointer; }))
|
||||
.def("__del__", [](SamePointer&) { py::print("__del__ called"); });
|
||||
|
||||
struct Empty {};
|
||||
py::class_<Empty>(m, "Empty")
|
||||
.def(py::init<>());
|
||||
}
|
||||
|
||||
template <int N> class BreaksBase { public:
|
||||
|
@ -368,3 +368,18 @@ def test_non_final_final():
|
||||
def test_exception_rvalue_abort():
|
||||
with pytest.raises(RuntimeError):
|
||||
m.PyPrintDestructor().throw_something()
|
||||
|
||||
|
||||
# https://github.com/pybind/pybind11/issues/1568
|
||||
def test_multiple_instances_with_same_pointer(capture):
|
||||
n = 100
|
||||
instances = [m.SamePointer() for _ in range(n)]
|
||||
for i in range(n):
|
||||
# We need to reuse the same allocated memory for with a different type,
|
||||
# to ensure the bug in `deregister_instance_impl` is detected. Otherwise
|
||||
# `Py_TYPE(self) == Py_TYPE(it->second)` will still succeed, even though
|
||||
# the `instance` is already deleted.
|
||||
instances[i] = m.Empty()
|
||||
# No assert: if this does not trigger the error
|
||||
# pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
|
||||
# and just completes without crashing, we're good.
|
||||
|
Loading…
Reference in New Issue
Block a user