Skip to content

Commit cb3d406

Browse files
bennorthjagerman
authored andcommitted
Fix refcounting for tp_base objects of new types (#950)
To fix a difficult-to-reproduce segfault on Python interpreter exit, ensure that the tp_base field of a handful of new heap-types is counted as a reference to that base type object.
1 parent 60526d4 commit cb3d406

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

include/pybind11/class_support.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
NAMESPACE_BEGIN(pybind11)
1515
NAMESPACE_BEGIN(detail)
1616

17+
inline PyTypeObject *type_incref(PyTypeObject *type) {
18+
Py_INCREF(type);
19+
return type;
20+
}
21+
1722
#if !defined(PYPY_VERSION)
1823

1924
/// `pybind11_static_property.__get__()`: Always pass the class instead of the instance.
@@ -49,7 +54,7 @@ inline PyTypeObject *make_static_property_type() {
4954

5055
auto type = &heap_type->ht_type;
5156
type->tp_name = name;
52-
type->tp_base = &PyProperty_Type;
57+
type->tp_base = type_incref(&PyProperty_Type);
5358
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
5459
type->tp_descr_get = pybind11_static_get;
5560
type->tp_descr_set = pybind11_static_set;
@@ -162,7 +167,7 @@ inline PyTypeObject* make_default_metaclass() {
162167

163168
auto type = &heap_type->ht_type;
164169
type->tp_name = name;
165-
type->tp_base = &PyType_Type;
170+
type->tp_base = type_incref(&PyType_Type);
166171
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
167172

168173
type->tp_setattro = pybind11_meta_setattro;
@@ -361,7 +366,7 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
361366

362367
auto type = &heap_type->ht_type;
363368
type->tp_name = name;
364-
type->tp_base = &PyBaseObject_Type;
369+
type->tp_base = type_incref(&PyBaseObject_Type);
365370
type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
366371
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
367372

@@ -552,7 +557,7 @@ inline PyObject* make_new_python_type(const type_record &rec) {
552557
auto type = &heap_type->ht_type;
553558
type->tp_name = strdup(full_name.c_str());
554559
type->tp_doc = tp_doc;
555-
type->tp_base = (PyTypeObject *) handle(base).inc_ref().ptr();
560+
type->tp_base = type_incref((PyTypeObject *)base);
556561
type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
557562
if (bases.size() > 0)
558563
type->tp_bases = bases.release().ptr();

0 commit comments

Comments
 (0)