[PyKDE] PyQt4/win32 crash
K.S.Sreeram
sreeram at tachyontech.net
Sun Sep 17 21:22:56 BST 2006
K.S.Sreeram wrote:
> Phil Thompson wrote:
>> On Friday 15 September 2006 9:58 pm, K.S.Sreeram wrote:
>>> [Qt-4.1.4, sip-4.4.5, PyQt-4.0.1, Python-2.4.3, MSVC-7.1]
>>>
>>> Hi all,
>>>
>>> I've been facing a random crash in my app for sometime, and i've got it
>>> down to a simple test program. Run the attached script, click "Click Me"
>>> and close the newly opened window, and it crashes!
>>>
>>> I used debug builds and poked around the code, and here's why i think
>>> its crashing...
>>>
>>> The crash happens when a top-level window is closed, and all python
>>> references to the window are lost in the 'closeEvent' method.
>>>
>>> When a window is closed using the close button at the right top of the
>>> window, the Qt function "QWidgetPrivate::close_helper(mode)" gets called
>>> with "mode == CloseWithSpontaneousEvent". This function is there in
>>> src/gui/kernel/qwidget.cpp line 4609.
>>>
>>> In this function, close event is sent to the widget if mode is
>>> CloseWithSpontaneousEvent, as in this case. By the time, the close event
>>> is handled by the widget, the widget is already deleted because of
>>> python's gc.
>>>
>>> The Qt code seems to check for this case using tests like
>>> "that.isNull()". But on line 4642, the check for null is not performed
>>> and the app crashes at that point.
>>>
>>> So this looks like it is a bug in Qt itself. But is there someway PyQt
>>> can workaround this bug?
>> What if you swap the two lines of MyWindow.closeEvent()?
>
> That doesn't help. The last python reference is actually the 'self'
> parameter to the closeEvent. So the python gc kicks in only /after/ the
> return from closeEvent.
>
> As a workaround, i'm currently just planning to use a single shot timer
> to keep a reference to the object until after the close fully completes.
Here's the actual workaround i'm using:
_delayed = []
_timer = None
def _onTimer() :
global _timer
del _delayed[:]
_timer = None
def delaygc( obj ) :
global _timer
_delayed.append( obj )
if _timer is not None :
_timer.stop()
_timer = QtCore.QTimer()
_timer.setSingleShot( True )
_timer.start( 1000 )
QtCore.QObject.connect( _timer, QtCore.SIGNAL('timeout()'), _onTimer )
Just insert 'delaygc(self)' into 'closeEvent' methods and the app
doesn't crash anymore!
[sreeram;]
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 252 bytes
Desc: OpenPGP digital signature
Url : http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20060917/871fc7ec/signature.bin
More information about the PyQt
mailing list