Skip to content

Commit 080f303

Browse files
usiemsmrbean-bremen
authored andcommitted
Revert "Fix reference/memory leaks"
This reverts commit 06860d4.
1 parent 4aaf2d7 commit 080f303

5 files changed

+71
-107
lines changed

src/PythonQt.cpp

Lines changed: 55 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -379,23 +379,18 @@ PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
379379
PythonQt::~PythonQt() {
380380
delete _p;
381381
_p = NULL;
382-
383-
Py_DECREF(&PythonQtSlotFunction_Type);
384-
Py_DECREF(&PythonQtSignalFunction_Type);
385-
Py_DECREF(&PythonQtSlotDecorator_Type);
386-
Py_DECREF(&PythonQtProperty_Type);
387-
Py_DECREF(&PythonQtBoolResult_Type);
388-
Py_DECREF(&PythonQtClassWrapper_Type);
389-
Py_DECREF(&PythonQtInstanceWrapper_Type);
390-
Py_DECREF(&PythonQtStdOutRedirectType);
391-
Py_DECREF(&PythonQtStdInRedirectType);
392382
}
393383

394384
PythonQtPrivate::~PythonQtPrivate() {
395385
delete _defaultImporter;
396386
_defaultImporter = NULL;
397387

398-
qDeleteAll(_knownClassInfos);
388+
{
389+
QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
390+
while (i.hasNext()) {
391+
delete i.next().value();
392+
}
393+
}
399394

400395
PythonQtMethodInfo::cleanupCachedMethodInfos();
401396
PythonQtArgumentFrame::cleanupFreeList();
@@ -414,9 +409,7 @@ void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void *
414409

415410
// Backup original 'sys.stdin' if not yet done
416411
if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") ) {
417-
PyObject *stdin = PyObject_GetAttrString(sys.object(), "stdin");
418-
PyObject_SetAttrString(sys.object(), "pythonqt_original_stdin", stdin);
419-
Py_XDECREF(stdin);
412+
PyObject_SetAttrString(sys.object(), "pythonqt_original_stdin", PyObject_GetAttrString(sys.object(), "stdin"));
420413
}
421414

422415
in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
@@ -435,19 +428,15 @@ void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
435428
PythonQtObjectPtr sys;
436429
sys.setNewRef(PyImport_ImportModule("sys"));
437430

438-
PythonQtObjectPtr stdin;
439431
if (enabled) {
440-
if( PyObject_HasAttrString(sys.object(), "pythonqt_stdin") ) {
441-
stdin.setNewRef(PyObject_GetAttrString(sys.object(), "pythonqt_stdin"));
432+
if( !PyObject_HasAttrString(sys.object(), "pythonqt_stdin") ) {
433+
PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_stdin"));
442434
}
443435
} else {
444-
if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") ) {
445-
stdin.setNewRef(PyObject_GetAttrString(sys.object(), "pythonqt_original_stdin"));
436+
if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") ) {
437+
PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_original_stdin"));
446438
}
447439
}
448-
if (stdin) {
449-
PyObject_SetAttrString(sys.object(), "stdin", stdin);
450-
}
451440
}
452441

453442
PythonQtImportFileInterface* PythonQt::importInterface()
@@ -459,7 +448,7 @@ void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
459448
{
460449
if (_self->_p->_noLongerWrappedCB) {
461450
(*_self->_p->_noLongerWrappedCB)(o);
462-
}
451+
};
463452
}
464453

465454
void PythonQt::setQObjectMissingAttributeCallback(PythonQtQObjectMissingAttributeCB* cb)
@@ -536,7 +525,6 @@ void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const
536525
PythonQtClassInfo* outerClassInfo = lookupClassInfoAndCreateIfNotPresent(outerClass);
537526
outerClassInfo->addNestedClass(info);
538527
} else {
539-
Py_INCREF(pyobj);
540528
PyModule_AddObject(pack, info->className(), pyobj);
541529
}
542530
if (!module && package && strncmp(package, "Qt", 2) == 0) {
@@ -546,7 +534,6 @@ void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const
546534
PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
547535
}
548536
info->setPythonQtClassWrapper(pyobj);
549-
Py_DECREF(pyobj);
550537
}
551538

552539
PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
@@ -561,7 +548,6 @@ PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
561548
// address, so probably that C++ wrapper has been deleted earlier and
562549
// now we see a QObject with the same address.
563550
// Do not use the old wrapper anymore.
564-
removeWrapperPointer(obj);
565551
wrap = NULL;
566552
}
567553
if (!wrap) {
@@ -747,7 +733,6 @@ PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtCla
747733
PyObject* typeDict = PyDict_New();
748734
PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
749735
PyDict_SetItemString(typeDict, "__module__", moduleName);
750-
Py_DECREF(moduleName);
751736

752737
PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
753738

@@ -784,7 +769,6 @@ PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, Py
784769
PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
785770
PyObject* typeDict = PyDict_New();
786771
PyDict_SetItemString(typeDict, "__module__", module);
787-
Py_DECREF(module);
788772

789773
PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
790774

@@ -909,21 +893,17 @@ QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
909893
QVariant result;
910894
clearError();
911895
if (pycode) {
912-
PythonQtObjectPtr dict;
913-
PythonQtObjectPtr globals;
896+
PyObject* dict = NULL;
897+
PyObject* globals = NULL;
914898
if (PyModule_Check(object)) {
915899
dict = PyModule_GetDict(object);
916900
globals = dict;
917901
} else if (PyDict_Check(object)) {
918902
dict = object;
919903
globals = dict;
920904
} else {
921-
PyObject *moduleName = PyObject_GetAttrString(object, "__module__");
922-
PyObject *module = PyImport_ImportModule(PyString_AS_STRING(moduleName));
923-
dict.setNewRef(PyObject_GetAttrString(object, "__dict__"));
924-
globals.setNewRef(PyObject_GetAttrString(module, "__dict__"));
925-
Py_XDECREF(moduleName);
926-
Py_XDECREF(module);
905+
dict = PyObject_GetAttrString(object, "__dict__");
906+
globals = PyObject_GetAttrString(PyImport_ImportModule(PyString_AS_STRING(PyObject_GetAttrString(object, "__module__"))),"__dict__");
927907
}
928908
PyObject* r = NULL;
929909
if (dict) {
@@ -1068,30 +1048,24 @@ PythonQtObjectPtr PythonQt::createUniqueModule()
10681048

10691049
void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
10701050
{
1071-
PyObject *wrappedObject = _p->wrapQObject(qObject);
10721051
if (PyModule_Check(object)) {
1073-
Py_XINCREF(wrappedObject);
1074-
PyModule_AddObject(object, QStringToPythonCharPointer(name), wrappedObject);
1052+
PyModule_AddObject(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
10751053
} else if (PyDict_Check(object)) {
1076-
PyDict_SetItemString(object, QStringToPythonCharPointer(name), wrappedObject);
1054+
PyDict_SetItemString(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
10771055
} else {
1078-
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), wrappedObject);
1056+
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
10791057
}
1080-
Py_XDECREF(wrappedObject);
10811058
}
10821059

10831060
void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
10841061
{
1085-
PyObject *value = PythonQtConv::QVariantToPyObject(v);
10861062
if (PyModule_Check(object)) {
1087-
Py_XINCREF(value);
1088-
PyModule_AddObject(object, QStringToPythonCharPointer(name), value);
1063+
PyModule_AddObject(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
10891064
} else if (PyDict_Check(object)) {
1090-
PyDict_SetItemString(object, QStringToPythonCharPointer(name), value);
1065+
PyDict_SetItemString(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
10911066
} else {
1092-
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), value);
1067+
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
10931068
}
1094-
Py_XDECREF(value);
10951069
}
10961070

10971071
void PythonQt::removeVariable(PyObject* object, const QString& name)
@@ -1133,7 +1107,7 @@ QStringList PythonQt::introspection(PyObject* module, const QString& objectname,
11331107
} else {
11341108
object = lookupObject(module, objectname);
11351109
if (!object && type == CallOverloads) {
1136-
PythonQtObjectPtr dict = lookupObject(module, "__builtins__");
1110+
PyObject* dict = lookupObject(module, "__builtins__");
11371111
if (dict) {
11381112
object = PyDict_GetItemString(dict, QStringToPythonCharPointer(objectname));
11391113
}
@@ -1185,33 +1159,36 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
11851159
}
11861160
}
11871161
} else {
1188-
PythonQtObjectPtr keys;
1162+
PyObject* keys = NULL;
11891163
bool isDict = false;
11901164
if (PyDict_Check(object)) {
1191-
keys.setNewRef(PyDict_Keys(object));
1165+
keys = PyDict_Keys(object);
11921166
isDict = true;
11931167
} else {
11941168
#if defined(MEVISLAB) && !defined(PY3K)
11951169
int oldPy3kWarningFlag = Py_Py3kWarningFlag;
11961170
Py_Py3kWarningFlag = 0; // temporarily disable Python 3 warnings
1197-
keys.setNewRef(PyObject_Dir(object));
1171+
keys = PyObject_Dir(object);
11981172
Py_Py3kWarningFlag = oldPy3kWarningFlag;
11991173
#else
1200-
keys.setNewRef(PyObject_Dir(object));
1174+
keys = PyObject_Dir(object);
12011175
#endif
12021176
}
12031177
if (keys) {
12041178
int count = PyList_Size(keys);
1179+
PyObject* key;
1180+
PyObject* value;
1181+
QString keystr;
12051182
for (int i = 0;i<count;i++) {
1206-
PythonQtObjectPtr key = PyList_GetItem(keys,i);
1207-
PythonQtObjectPtr value;
1183+
key = PyList_GetItem(keys,i);
12081184
if (isDict) {
12091185
value = PyDict_GetItem(object, key);
1186+
Py_INCREF(value);
12101187
} else {
1211-
value.setNewRef(PyObject_GetAttr(object, key));
1188+
value = PyObject_GetAttr(object, key);
12121189
}
12131190
if (!value) continue;
1214-
QString keystr = PyString_AsString(key);
1191+
keystr = PyString_AsString(key);
12151192
static const QString underscoreStr("__tmp");
12161193
if (!keystr.startsWith(underscoreStr)) {
12171194
switch (type) {
@@ -1256,7 +1233,9 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
12561233
std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
12571234
}
12581235
}
1236+
Py_DECREF(value);
12591237
}
1238+
Py_DECREF(keys);
12601239
}
12611240
}
12621241
PyErr_Clear();
@@ -1309,7 +1288,6 @@ QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
13091288
PyObject* typeObject = getObjectByType(typeName);
13101289
if (typeObject) {
13111290
object = PyObject_GetAttrString(typeObject, QStringToPythonCharPointer(memberName));
1312-
Py_DECREF(typeObject);
13131291
}
13141292
}
13151293
if (object) {
@@ -1381,7 +1359,6 @@ PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList
13811359
PyObject* arg = PythonQtConv::QVariantToPyObject(it.value());
13821360
if (arg) {
13831361
PyDict_SetItemString(pkwargs, QStringToPythonCharPointer(it.key()), arg);
1384-
Py_DECREF(arg);
13851362
} else {
13861363
err = true;
13871364
break;
@@ -1773,7 +1750,7 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ
17731750
}
17741751
#ifdef PY3K
17751752
PythonQtModuleDef.m_name = name.constData();
1776-
_p->_pythonQtModule.setNewRef(PyModule_Create(&PythonQtModuleDef));
1753+
_p->_pythonQtModule = PyModule_Create(&PythonQtModuleDef);
17771754
#else
17781755
_p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
17791756
#endif
@@ -1813,11 +1790,7 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ
18131790
Py_XDECREF(old_module_names);
18141791

18151792
#ifdef PY3K
1816-
PyObject *modules = PyObject_GetAttrString(sys.object(), "modules");
1817-
PyObject *nameObj = PyUnicode_FromString(name.constData());
1818-
PyDict_SetItem(modules, nameObj, _p->_pythonQtModule.object());
1819-
Py_XDECREF(modules);
1820-
Py_XDECREF(nameObj);
1793+
PyDict_SetItem(PyObject_GetAttrString(sys.object(), "modules"), PyUnicode_FromString(name.constData()), _p->_pythonQtModule.object());
18211794
#endif
18221795
}
18231796

@@ -1837,8 +1810,7 @@ QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString&
18371810

18381811
QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
18391812
{
1840-
PythonQtObjectPtr typeObject;
1841-
typeObject.setNewRef(getObjectByType(typeName));
1813+
PythonQtObjectPtr typeObject = getObjectByType(typeName);
18421814
if (typeObject.isNull()) {
18431815
return "";
18441816
}
@@ -2133,12 +2105,10 @@ const QMetaObject* PythonQtPrivate::buildDynamicMetaObject(PythonQtClassWrapper*
21332105
builder.setClassName(((PyTypeObject*)type)->tp_name);
21342106

21352107
PyObject* dict = ((PyTypeObject*)type)->tp_dict;
2136-
Py_ssize_t pos = 0;
2108+
Py_ssize_t pos = NULL;
21372109
PyObject* value = NULL;
21382110
PyObject* key = NULL;
2139-
static PyObject* qtSlots = NULL;
2140-
if (!qtSlots)
2141-
qtSlots = PyString_FromString("_qtSlots");
2111+
static PyObject* qtSlots = PyString_FromString("_qtSlots");
21422112

21432113
bool needsMetaObject = false;
21442114
// Iterate over all members and check if they affect the QMetaObject:
@@ -2156,7 +2126,7 @@ const QMetaObject* PythonQtPrivate::buildDynamicMetaObject(PythonQtClassWrapper*
21562126
}
21572127
}
21582128
}
2159-
pos = 0;
2129+
pos = NULL;
21602130
value = NULL;
21612131
key = NULL;
21622132
// Now look for slots: (this is a bug in QMetaObjectBuilder, all signals need to be added first)
@@ -2190,11 +2160,10 @@ const QMetaObject* PythonQtPrivate::buildDynamicMetaObject(PythonQtClassWrapper*
21902160
}
21912161
if (PyFunction_Check(value) && PyObject_HasAttr(value, qtSlots)) {
21922162
// A function which has a "_qtSlots" signature list, add the slots to the meta object
2193-
PythonQtObjectPtr signatures;
2194-
signatures.setNewRef(PyObject_GetAttr(value, qtSlots));
2163+
PyObject* signatures = PyObject_GetAttr(value, qtSlots);
21952164
Py_ssize_t count = PyList_Size(signatures);
21962165
for (Py_ssize_t i = 0; i < count; i++) {
2197-
PyObject* signature = PyList_GET_ITEM(signatures.object(), i);
2166+
PyObject* signature = PyList_GET_ITEM(signatures, i);
21982167
QByteArray sig = PyString_AsString(signature);
21992168
// Split the return type and the rest of the signature,
22002169
// no spaces should be in the rest of the signature...
@@ -2240,11 +2209,9 @@ int PythonQtPrivate::handleMetaCall(QObject* object, PythonQtInstanceWrapper* wr
22402209
}
22412210
PythonQtProperty* prop = NULL;
22422211
// Get directly from the Python class, since we don't want to get the value of the property
2243-
PythonQtObjectPtr name, maybeProp;
2244-
name.setNewRef(PyString_FromString(metaProp.name()));
2245-
maybeProp.setNewRef(PyBaseObject_Type.tp_getattro((PyObject*)wrapper, name));
2212+
PyObject* maybeProp = PyBaseObject_Type.tp_getattro((PyObject*)wrapper, PyString_FromString(metaProp.name()));
22462213
if (maybeProp && PythonQtProperty_Check(maybeProp)) {
2247-
prop = (PythonQtProperty*)maybeProp.object();
2214+
prop = (PythonQtProperty*)maybeProp;
22482215
} else {
22492216
return id - methodCount;
22502217
}
@@ -2261,7 +2228,7 @@ int PythonQtPrivate::handleMetaCall(QObject* object, PythonQtInstanceWrapper* wr
22612228

22622229
PyObject* value = prop->data->callGetter((PyObject*)wrapper);
22632230
if (value) {
2264-
void* result = PythonQtConv::ConvertPythonToQt(info, value, false, NULL, args[0]); // FIXME: what happens with result? free?
2231+
void* result = PythonQtConv::ConvertPythonToQt(info, value, false, NULL, args[0]);
22652232
Py_DECREF(value);
22662233
return (result == NULL ? -1 : 0);
22672234
} else {
@@ -2300,15 +2267,17 @@ QString PythonQtPrivate::getSignature(PyObject* object)
23002267
PyMethodObject* method = NULL;
23012268
PyFunctionObject* func = NULL;
23022269

2270+
bool decrefMethod = false;
2271+
23032272
if (PythonQtUtils::isPythonClassType(object)) {
23042273
method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
2274+
decrefMethod = true;
23052275
} else if (object->ob_type == &PyFunction_Type) {
23062276
func = (PyFunctionObject*)object;
23072277
} else if (object->ob_type == &PyMethod_Type) {
23082278
method = (PyMethodObject*)object;
2309-
Py_XINCREF(method);
23102279
}
2311-
if (method) {
2280+
if (method) {
23122281
if (PyFunction_Check(method->im_func)) {
23132282
func = (PyFunctionObject*)method->im_func;
23142283
} else if (isMethodDescriptor((PyObject*)method)) {
@@ -2415,7 +2384,9 @@ QString PythonQtPrivate::getSignature(PyObject* object)
24152384
signature = funcName + "(" + signature + ")";
24162385
}
24172386

2418-
Py_XDECREF(method);
2387+
if (method && decrefMethod) {
2388+
Py_DECREF(method);
2389+
}
24192390
}
24202391

24212392
return signature;
@@ -2480,7 +2451,7 @@ PythonQtClassInfo* PythonQtPrivate::getClassInfo( const QByteArray& className )
24802451
if (_knownLazyClasses.contains(className)) {
24812452
QByteArray module = _knownLazyClasses.value(className);
24822453
recursion = true;
2483-
PyImport_ImportModule(module); // FIXME: reference leaked
2454+
PyImport_ImportModule(module);
24842455
recursion = false;
24852456
result = _knownClassInfos.value(className);
24862457
if (!result) {

src/PythonQt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
813813
PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
814814

815815
//! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
816-
QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects; // FIXME: remove unused entries in cleanup()
816+
QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
817817

818818
//! stores the meta info of known Qt classes
819819
QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;

0 commit comments

Comments
 (0)