diff options
Diffstat (limited to 'sources/shiboken2/libshiboken/basewrapper.cpp')
-rw-r--r-- | sources/shiboken2/libshiboken/basewrapper.cpp | 66 |
1 files changed, 59 insertions, 7 deletions
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index 000035627..4030fe1c4 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -58,6 +58,10 @@ #include "qapp_macro.h" #include "voidptr.h" +#if defined(__APPLE__) +#include <dlfcn.h> +#endif + namespace { void _destroyParentInfo(SbkObject *obj, bool keepReference); } @@ -74,6 +78,17 @@ static void callDestructor(const Shiboken::DtorAccumulatorVisitor::DestructorEnt extern "C" { +// PYSIDE-939: A general replacement for object_dealloc. +void Sbk_object_dealloc(PyObject *self) +{ + if (PepRuntime_38_flag) { + // PYSIDE-939: Handling references correctly. + // This was not needed before Python 3.8 (Python issue 35810) + Py_DECREF(Py_TYPE(self)); + } + Py_TYPE(self)->tp_free(self); +} + static void SbkObjectTypeDealloc(PyObject *pyObj); static PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds); @@ -309,8 +324,32 @@ static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete) // Need to decref the type if this is the dealloc func; if type // is subclassed, that dealloc func will decref (see subtype_dealloc // in typeobject.c in the python sources) - bool needTypeDecref = (PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapper + bool needTypeDecref = (false + || PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapper || PyType_GetSlot(pyType, Py_tp_dealloc) == SbkDeallocWrapperWithPrivateDtor); + if (PepRuntime_38_flag) { + // PYSIDE-939: Additional rule: Also when a subtype is heap allocated, + // then the subtype_dealloc deref will be suppressed, and we need again + // to supply a decref. + needTypeDecref |= (pyType->tp_base->tp_flags & Py_TPFLAGS_HEAPTYPE) != 0; + } + +#if defined(__APPLE__) + // Just checking once that our assumptions are right. + if (false) { + void *p = PyType_GetSlot(pyType, Py_tp_dealloc); + Dl_info dl_info; + dladdr(p, &dl_info); + fprintf(stderr, "tp_dealloc is %s\n", dl_info.dli_sname); + } + // Gives one of our functions + // "Sbk_object_dealloc" + // "SbkDeallocWrapperWithPrivateDtor" + // "SbkDeallocQAppWrapper" + // "SbkDeallocWrapper" + // but for typedealloc_test.py we get + // "subtype_dealloc" +#endif // Ensure that the GC is no longer tracking this object to avoid a // possible reentrancy problem. Since there are multiple steps involved @@ -369,6 +408,11 @@ static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete) if (needTypeDecref) Py_DECREF(pyType); + if (PepRuntime_38_flag) { + // PYSIDE-939: Handling references correctly. + // This was not needed before Python 3.8 (Python issue 35810) + Py_DECREF(pyType); + } } void SbkDeallocWrapper(PyObject *pyObj) @@ -412,6 +456,11 @@ void SbkObjectTypeDealloc(PyObject *pyObj) #ifndef Py_LIMITED_API Py_TRASHCAN_SAFE_END(pyObj); #endif + if (PepRuntime_38_flag) { + // PYSIDE-939: Handling references correctly. + // This was not needed before Python 3.8 (Python issue 35810) + Py_DECREF(Py_TYPE(pyObj)); + } } PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds) @@ -453,7 +502,16 @@ PyObject *SbkObjectTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *k // The meta type creates a new type when the Python programmer extends a wrapped C++ class. auto type_new = reinterpret_cast<newfunc>(PyType_Type.tp_new); + + // PYSIDE-939: This is a temporary patch that circumvents the problem + // with Py_TPFLAGS_METHOD_DESCRIPTOR until this is finally solved. + PyObject *ob_PyType_Type = reinterpret_cast<PyObject *>(&PyType_Type); + PyObject *mro = PyObject_GetAttr(ob_PyType_Type, Shiboken::PyName::mro()); + auto hold = Py_TYPE(mro)->tp_flags; + Py_TYPE(mro)->tp_flags &= ~Py_TPFLAGS_METHOD_DESCRIPTOR; auto *newType = reinterpret_cast<SbkObjectType *>(type_new(metatype, args, kwds)); + Py_TYPE(mro)->tp_flags = hold; + if (!newType) return nullptr; #if PY_VERSION_HEX < 0x03000000 @@ -554,12 +612,6 @@ PyObject *SbkQAppTpNew(PyTypeObject *subtype, PyObject *, PyObject *) return self == nullptr ? nullptr : _setupNew(self, subtype); } -void -object_dealloc(PyObject *self) -{ - Py_TYPE(self)->tp_free(self); -} - PyObject * SbkDummyNew(PyTypeObject *type, PyObject *, PyObject *) { |