aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken/basewrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/libshiboken/basewrapper.cpp')
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp66
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 *)
{