boostorg / boostorg/python

with_custodian_and_ward doesn't guarantee destructor ordering

未关闭
#128 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
C++
星标
537
派生
223
平均合并
11 小时 22 分钟
30 天内合并 PR
2

描述

The weakref trick used by `with_custodian_and_ward` relies on the nurse object being cleared before it calls the callback which drops the reference to the patient. This is mostly but not always true: when the cyclic garbage collector runs, it first makes all weakref callbacks before freeing the garbage (at least in Python 2.7.12). This can lead to the patient's destructor running before the nurse's, with dire consequences if the nurse references the patient in its destructor.

pybind11 uses the same weakref trick and suffers the same bug: https://github.com/pybind/pybind11/issues/856.

## Example code

keepalive.cpp:
```c++
#include
#include

namespace py = boost::python;

class B;

class A {
private:
B &b;
public:
A(B &b) : b(b) {}
~A() { std::cerr << "In A::~A()\n"; }
};

class B {
public:
~B() { std::cerr << "In B::~B()\n"; }
};

BOOST_PYTHON_MODULE(keepalive) {
py::class_("A", py::init()[py::with_custodian_and_ward<1, 2>()]);
py::class_("B");
}
```

test.py:
```python
#!/usr/bin/env python
from keepalive import A, B

lst = [A(B())]
lst.append(lst)
del lst
```

Output:
```
In B::~B()
In A::~A()
```

贡献指南

这个仓库没有索引到贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。