with_custodian_and_ward doesn't guarantee destructor ordering
- Linguagem predominante
- C++
- Estrelas
- 537
- Forks
- 223
- Merge médio
- 11h 22min
- PRs com merge (30d)
- 2
Descrição
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()
```
Guia de contribuição
Nenhum guia de contribuição indexado para este repositório
Direção de pesquisa
Start with the reproducer in keepalive.cpp and test.py, then run it under the affected garbage-collection scenario described in the issue. Trace with_custodian_and_ward's weakref callback and destructor behavior; done means the patient's lifetime cannot end before the nurse when cyclic garbage collection occurs.
Escrita pelo modelo de indexação a partir do texto da issue.
Avaliação
- Stack de tecnologia
- cpp, python
- Domínio
- api, backend
- Tipo de issue
- Bug
- Dificuldade
- 5/5
- Tempo estimado
- Mais de uma semana
- Status de atividade
- Estagnada
- Clareza
- Razoavelmente clara
- Facilidade para iniciantes
- 30/100