Hi,

I finally got around writting a simple test case to demonstrate
the deadlock in the signal/slot new style connections.

The test case can be ran using the following command :

python -m nose.core -v -s test_deadlock.py:SignalSlotCase

depending on the speed of your computer, it might take some
tweaking to observe the deadlock, it occurs when 'emitted' and
'connected' are printed on the screen at the same time.

Here are some interesting observations :

- the deadlock happens independent of the QT / PyQT version
- the old_style never deadlocks
- this example won't work at all using PySide, it seems that PySide
  doesn't support queued connections involving python objects.

I'm not sure what I have to do with this issue, is this a Qt, Python
or PyQt issue ??

Thanks,

Erik
Thread 1
========

#0  0x0012d422 in __kernel_vsyscall ()
#1  0x0013a245 in sem_wait@@GLIBC_2.1 () at 
../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/sem_wait.S:80
#2  0x0810abe8 in PyThread_acquire_lock (lock=0x85debb8, waitflag=1) at 
../Python/thread_pthread.h:349
#3  0x080dbe9c in PyEval_RestoreThread (tstate=0x8281060) at 
../Python/ceval.c:353
#4  0x080fdc78 in PyGILState_Ensure () at ../Python/pystate.c:592
#5  0x01dc8a06 in ?? () from /usr/lib/pymodules/python2.6/PyQt4/QtCore.so
#6  0x01dc495b in ?? () from /usr/lib/pymodules/python2.6/PyQt4/QtCore.so
#7  0x016423d8 in QMetaType::construct (type=257, copy=0x87d1950) at 
kernel/qmetatype.cpp:1116
#8  0x016491cc in queued_activate (sender=<value optimized out>, signal=<value 
optimized out>, c=0xb7201dd8, argv=0x87c06d0, semaphore=0x0) at 
kernel/qobject.cpp:3166
#9  0x0164b2b1 in QMetaObject::activate (sender=0x87bf998, m=0x87bf570, 
local_signal_index=0, argv=0x87c06d0) at kernel/qobject.cpp:3266
#10 0x0164b9ea in QMetaObject::activate (sender=0x87bf998, signal_index=4, 
argv=0x87c06d0) at kernel/qobject.cpp:3346
#11 0x0164ba2b in QMetaObject::activate (sender=0x87bf998, from_signal_index=4, 
to_signal_index=4, argv=0x87c06d0) at kernel/qobject.cpp:3204
#12 0x01dcbda4 in ?? () from /usr/lib/pymodules/python2.6/PyQt4/QtCore.so
#13 0x01dc4aec in ?? () from /usr/lib/pymodules/python2.6/PyQt4/QtCore.so

Thread 2
========

#0  0x0012d422 in __kernel_vsyscall ()
#1  0x00138015 in pthread_cond_wait@@GLIBC_2.3.2 () at 
../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_wait.S:122
#2  0x015348c2 in QMutexPrivate::wait (this=0xb7201ec0, timeout=-1) at 
thread/qmutex_unix.cpp:84
#3  0x01530072 in QMutex::lock (this=0xb7201eb0) at thread/qmutex.cpp:205
#4  0x01649dfb in QOrderedMutexLocker::relock (sender=0x87bf998, 
signal_index=2, receiver=0xb72020d8, method_index=4, type=0, types=0x0) at 
../../include/QtCore/private/../../../src/corelib/thread/qorderedmutexlocker_p.h:83
#5  QOrderedMutexLocker (sender=0x87bf998, signal_index=2, receiver=0xb72020d8, 
method_index=4, type=0, types=0x0) at 
../../include/QtCore/private/../../../src/corelib/thread/qorderedmutexlocker_p.h:72
#6  QMetaObjectPrivate::connect (sender=0x87bf998, signal_index=2, 
receiver=0xb72020d8, method_index=4, type=0, types=0x0) at 
kernel/qobject.cpp:2908
#7  0x0164a3b2 in QObject::connect (sender=0x87bf998, signal=0x877ab00 
"2my_signal(PyQt_PyObject)", receiver=0xb72020d8, method=0xb7202180 
"1my_slot(PyQt_PyObject)", type=Qt::AutoConnection) at kernel/qobject.cpp:2607
#8  0x01dc4f46 in ?? () from /usr/lib/pymodules/python2.6/PyQt4/QtCore.so
#9  0x01dc59e6 in ?? () from /usr/lib/pymodules/python2.6/PyQt4/QtCore.so


"""Test the behaviour of the qt bindings in various circumstances.
"""

import unittest

from PyQt4 import QtCore

class SignalSlotCase( unittest.TestCase ):
    
    def setUp(self):
        import sys
        self.app = QtCore.QCoreApplication(sys.argv)

    def test_multiple_threads(self):
        
        class SignalEmitter(QtCore.QObject):
            
            my_signal = QtCore.pyqtSignal(object)
            
            def start_emitting(self):
                for i in range(1000):
                    o = object()
                    self.my_signal.emit(o)
                    print 'emitted', i
        
        class SignalReceiver(QtCore.QObject):
            
            @QtCore.pyqtSlot(object)
            def my_slot(self, obj):
                print 'signal received', obj
            
        emitter = SignalEmitter()
        
        class ReceivingThread(QtCore.QThread):
            
            def run(self):
                receivers = []
                for i in range(1000):
                    receiver = SignalReceiver()
                    emitter.my_signal.connect( receiver.my_slot )
                    receivers.append(receiver)
                    print 'connected', i
                    
        thread = ReceivingThread()
        thread.start()
        emitter.start_emitting()
        thread.wait()
"""Test the behaviour of the qt bindings in various circumstances.
"""

import unittest

from PyQt4 import QtCore

class SignalSlotCase( unittest.TestCase ):
    
    def setUp(self):
        import sys
        self.app = QtCore.QCoreApplication(sys.argv)

    def test_multiple_threads(self):
        
        my_signal = QtCore.SIGNAL('my_signal')
        
        class SignalEmitter(QtCore.QObject):
                
            def start_emitting(self):
                for i in range(1000):
                    o = object()
                    self.emit( my_signal, o )
                    print 'emitted', i
        
        class SignalReceiver(QtCore.QObject):
            
            def my_slot(self, obj):
                print 'signal received', obj
            
        emitter = SignalEmitter()
        
        class ReceivingThread(QtCore.QThread):
            
            def run(self):
                receivers = []
                for i in range(1000):
                    receiver = SignalReceiver()
                    QtCore.QObject.connect( emitter, my_signal, receiver.my_slot, QtCore.Qt.QueuedConnection )
                    receivers.append(receiver)
                    print 'connected', i
                    
        thread = ReceivingThread()
        thread.start()
        emitter.start_emitting()
        thread.wait()
_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to