Skip to content

Fix reference/memory leaks #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 12, 2020
Merged

Conversation

gregor-anich-uibk
Copy link
Contributor

Tested with Python-3.8.5 debug build and memcheck, does not fix all leaks but some, reduces dynamic memory leaks by 2/3rds

Copy link
Collaborator

@florianlink florianlink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good and you seem to know your business! I always hated these Api differences (which call steals and which doesn't). I will ask another colleague to have a look as well and then we can merge this.

src/PythonQt.cpp Outdated
@@ -525,6 +536,7 @@ void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const
PythonQtClassInfo* outerClassInfo = lookupClassInfoAndCreateIfNotPresent(outerClass);
outerClassInfo->addNestedClass(info);
} else {
Py_INCREF(pyobj);
PyModule_AddObject(pack, info->className(), pyobj);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyModule_AddObject only decrements the reference count on success, so you should check the return code.

Copy link
Contributor Author

@gregor-anich-uibk gregor-anich-uibk Oct 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I saw this, there are many more such calls and I thought I leave it up for the next round of fixing, but now I fixed all of them by adding a wrapper function to do the job.

src/PythonQt.cpp Outdated
if (PyModule_Check(object)) {
PyModule_AddObject(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
Py_XINCREF(wrappedObject);
PyModule_AddObject(object, QStringToPythonCharPointer(name), wrappedObject);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyModule_AddObject only decrements the reference count on success, so you should check the return code.

Copy link
Contributor

@usiems usiems left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please have a look at the inline comments.

src/PythonQt.cpp Outdated
if (PyModule_Check(object)) {
PyModule_AddObject(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
Py_XINCREF(value);
PyModule_AddObject(object, QStringToPythonCharPointer(name), value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyModule_AddObject only decrements the reference count on success, so you should check the return code.

src/PythonQt.cpp Outdated
PyObject* value = NULL;
PyObject* key = NULL;
static PyObject* qtSlots = PyString_FromString("_qtSlots");
static PyObject* qtSlots = NULL;
if (!qtSlots)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use braces even for one-line blocks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (err != 0) {
Py_DECREF(code);
Py_DECREF(mod);
return NULL;
}
#endif
}
Py_DECREF(mod);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct? The documentation states that PyModule_AddModule returns a borrowed reference. But I see that Py_DECREF is also used on mod before, so it seems as if this is the correct way to do this...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch, I probably wrongly assumed the existing code was correct but you are right, documentation says it returns a borrowed reference so I removed all the DECREFs.

build/python.prf Outdated
unix:QMAKE_CXXFLAGS += $$system(python$${PYTHON_VERSION}-config --includes)
}
unix:QMAKE_CXXFLAGS += $$system(python$${PYTHON_VERSION}-config --includes)
unix:QMAKE_LFLAGS += $$system(python$${PYTHON_VERSION}-config --ldflags)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to add this line to build against Python-3.8.5 on my OpenSuSE machine

@gregor-anich-uibk
Copy link
Contributor Author

I tried to address the issues you showed up, please let me know if it's now fine to be committed. I wish I had the time to do a proper fixup/cleanup of PythonQt, but I found that Python itself cannot really clean up all the memory which surprised me, it's a nice language and I really like to use it for scripting my application, but I'll have to live with small leaks 😄

@usiems
Copy link
Contributor

usiems commented Oct 12, 2020

I have no objections to this merge request. Florian?

@florianlink
Copy link
Collaborator

florianlink commented Oct 12, 2020 via email

@usiems usiems merged commit 7a2b8f3 into MeVisLab:master Oct 12, 2020
@gregor-anich-uibk
Copy link
Contributor Author

Nice, thanks, will contribute again if I do more fixes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants