PySide Bugzilla Closed for New Bugs

PySide is now a Qt Add-on and uses the Qt Project's JIRA Bug Tracker instead of this Bugzilla instance. This Bugzilla is left for reference purposes.

Bug 910 - installEventFilter() increments reference count on target object
: installEventFilter() increments reference count on target object
Status: CLOSED FIXED
Product: PySide
Classification: Unclassified
Component: PySide
: HEAD
: PC Linux
: P3 critical
Assigned To: renato filho
:
:
:
  Show dependency treegraph
 
Reported: 2011-07-02 12:33 EEST by john haddon
Modified: 2011-07-22 22:12 EEST (History)
8 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description john haddon 2011-07-02 12:33:14 EEST
It appears that when calling installEventFilter() to add a filter to an object,
the reference count of that object is being incremented, meaning that the
object will never die. This is not the case with PyQt. Here's an example script
to demonstrate the problem :

import sys
import weakref

from PySide import QtGui
from PySide import QtCore

class EventFilter( QtCore.QObject ) :

    def __init__( self ) :

        QtCore.QObject.__init__( self )

    def eventFilter( self, qObject, qEvent ) :

        return False

app = QtGui.QApplication( [] )

w = QtGui.QWidget( None, QtCore.Qt.WindowFlags( QtCore.Qt.Window ) )

f = EventFilter()

print sys.getrefcount( w )
w.installEventFilter( f )
print sys.getrefcount( w )

w.show()

r = weakref.ref( w )

del w

print r()

app.exec_()

When running this using PyQt no window is displayed (as it has been deleted as
expected) and I see the following output :

2
2
None

When running using PySide the window is displayed unexpectedly and the
following is output :

2
3
<PySide.QtGui.QWidget object at 0x2e0d8c0>
Comment 1 renato filho 2011-07-04 19:44:56 EEST
In PySide we have this to avoid strange code behaviour.

the pyside function installEventFilter increase the reference to avoid the
crash, in some cases when the object is destroyed before the listener.

But the reference is decremented if the listener is destroyed, or you can use
removeEventFilter to decrease the reference.

With this we can ensure the good work of the code, and make sure all events
will be delivery on eventFilter function with the same python object.
Comment 2 john haddon 2011-07-04 20:13:17 EEST
In my case I have a global event filter object which I'm applying to all my
QWidgets - so the listener will never be destroyed. I want to just unparent a
widget and drop any python references to it and have it be destroyed, and that
is exactly what happens in PyQt.

To me it is a strange code behaviour that this does not happen with PySide. Is
it not more appropriate to increment a reference on the event listener rather
than on the event source? And remove the reference to the listener when the
source dies or when the listener is removed?
Comment 3 renato filho 2011-07-04 20:39:10 EEST
if you remove the listener with "removeEventFilter" the reference will be
decremented.
Comment 4 john haddon 2011-07-04 21:38:57 EEST
Thanks Renato, I understand that I can remove the event filter but that's not
always as simple as you make it sound. In a situation where widgets may be
parented and unparented and reparented repeatedly in an application it's often
not known at unparenting time whether it will be reparented or not (if it isn't
reparented then I expect it to die). I think I will need to remove the event
filter whenever a widget is unparented and replace it whenever it's reparented,
unless it's a top level window without a parent in which case I don't know what
I will do.

A major goal of mine is to have my code work with both PyQt and PySide, so it's
a pity any time the code has to deviate for one or the other. I may be being
ignorant but I don't understand why the listener holds a reference to the
source - I would presume that the source needs a reference to the listener but
not the other way around. I have seen no crashes at all with PyQt, ever, in any
circumstance, so I believe it is possible to do without making it hard for a
widget to die.
Comment 5 renato filho 2011-07-05 01:32:55 EEST
I agree with you I will mark this a valid bug to be fixed soon.

Thanks
Comment 6 john haddon 2011-07-05 03:45:37 EEST
Thanks Renato - let me know if I can help out in any way...
Comment 7 Marcelo Lira 2011-07-22 00:35:39 EEST
Fixed in PySide/2e98f87d.
Comment 8 renato filho 2011-07-22 22:12:44 EEST
release 1.0.5