[BUG]: make_static_property_type() is incompatible with Python 3.13 ands leads to a crash
vstinner opened this issue · comments
Required prerequisites
- Make sure you've read the documentation. Your issue may be addressed there.
- Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
- Consider asking first in the Gitter chat room or in a Discussion.
What version (or hash if on master) of pybind11 are you using?
2.11.1
Problem description
Running python-contourpy tests on Python 3.13 does crash. Using a Python debug build, the following assertion fails:
+ python3-debug -c 'import contourpy'
python3-debug: /builddir/build/BUILD/Python-3.13.0a2/Objects/dictobject.c:5473: _PyObject_InitInlineValues: Assertion `keys != NULL' failed.
The problem is the pybind11_static_property
type created as a Python heap type in make_static_property_type()
of pybind11/include/pybind11/detail/class.h
which sets the Py_TPFLAGS_MANAGED_DICT
flag after calling PyType_Ready()
. Maybe it worked on Python 3.12, but it no longer works on Python 3.13 which requires the flag to be set before calling PyType_Ready()
.
Fedora downstream issue about the contourpy crash: https://bugzilla.redhat.com/show_bug.cgi?id=2252083
Note: I tested the Fedora package python3-pybind11-2.11.1-1.fc40.x86_64.
Reproducible example code
I'm sorry, right now I have no short reproducer :-(
Is this a regression? Put the last known working version here if it is.
Work on Python 3.12, crash on Python 3.13
The issue is quite tricky. Context:
- pybind11: #4092
- Python doc: https://docs.python.org/dev/c-api/typeobj.html#c.Py_TPFLAGS_MANAGED_DICT
I wrote #4971 to fix the issue.
By the way, the following code in include/pybind11/detail/class.h
can now be updated to use the new function: PyObject_VisitManagedDict() (new in Python 3.13)
extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) {
PyObject *&dict = *_PyObject_GetDictPtr(self);
Py_VISIT(dict);
And the following code can be updated to use: PyObject_ClearManagedDict() (new in Python 3.13)
extern "C" inline int pybind11_clear(PyObject *self) {
PyObject *&dict = *_PyObject_GetDictPtr(self);
Py_CLEAR(dict);
By the way, the following code in include/pybind11/detail/class.h can now be updated
Is there a chance that you could send a PR with that change?
Is there a chance that you could send a PR with that change?
I created #4973 to use PyObject_VisitManagedDict() and PyObject_ClearManagedDict().
Closed by #4973