[PyKDE] QCustomEvent Subclass and Seg Faults

Phil Thompson phil at riverbankcomputing.co.uk
Tue Jun 17 15:21:01 BST 2003


On Monday 16 June 2003 11:00 pm, Troy Melhase wrote:
> Hi All:
>
> I have a QCustomEvent class that's somehow related to intermittant
> segfaults. My app ismulti-threaded, and one of the threads reads socket
> data, turns the data into an object,and delivers the object to other
> interested objects.
>
> The socket-reader thread calls methods of a proxy class, listed below. 
> These methods then create the QCustomEvent subclass instances and post them
> to the application.  Here's the proxy and it's helper function:
>
> def mk_signal(signal_name):
>     def inner_ib_method(self, event):
>         self.count_incoming()
> 	## this creates an instance of the custom event subclass
> 	## 'event' is the object created by the socket reader thread
>         broker_event = BrokerSocketDataEvent(signal_name, event)
> 	try:
>             QApplication.postEvent(self.parent, broker_event)
>         except AttributeError:
>             pass
>     return inner_ib_method
>
> class BrokerEventGuiProxy(QObject):
>     def __init__(self, parent, connection):
>         self.parent = parent
>         self.message_counters = {}
>
>     def count_incoming(self):
>         hour = time.localtime()[3]
>         self.message_counters.setdefault(hour, 0)
>         self.message_counters[hour] += 1
>
>     ib_account = mk_signal('BrokerUpdateAccountValue')
>     ib_error = mk_signal('BrokerError')
>     ib_execution_details = mk_signal('BrokerExecutionDetails')
>     ib_open_order = mk_signal('BrokerOpenOrder')
>     ib_order_status = mk_signal('BrokerOrderStatus')
>     ib_ticker = mk_signal('BrokerTickerMessage')
>     ib_market_depth = mk_signal('BrokerUpdateMarketDepth')
>     ib_portfolio = mk_signal('BrokerUpdatePortfolio')
>     ib_reader_stop = mk_signal('BrokerDisconnected')
>
> And here is the QCustomEvent subclass:
>
> class BrokerSocketDataEvent(QCustomEvent):
>     names = ['BrokerError',
>              'BrokerExecutionDetails',
>              'BrokerOpenOrder',
>              'BrokerOrderStatus',
>              'BrokerTickerMessage',
>              'BrokerUpdateAccountValue',
>              'BrokerUpdateMarketDepth',
>              'BrokerUpdatePortfolio',
>              'BrokerDisconnected', ]
>     names_lookup = dict(zip(names, range(QEvent.User, \
>     	QEvent.User + len(names))))
>
>     def __init__(self, name, data):
>         event_key = self.names_lookup[name]
>         QCustomEvent.__init__(self, event_key, (name, data))
>
>
> In my main window, I have a customEvent method defined to handle
> these events:
>
>     def customEvent(self, event):
>         if isinstance(event, (BrokerSocketDataEvent, )):
>             sig, broker_signal = event.data()
>             self.emit(PYSIGNAL(sig), (broker_signal, ))
>
>
> Typically, this app processes about 10-15 of these objects per second.
> Sometimes the app will segfault after just a few hours, sometimes not at
> all. There doesn't seem to be a repeatable sequence of user actions that
> causes the behavior.
>
> Originally, I was propagating the objects by first acquiring the Qt library
> mutex and calling GUI object methods directly.  This worked and never
> caused a segfault, but chewed up 10% more CPU and made the GUI feel much
> less responsive.  Those reasons led me to the proxy solution above.
>
> Interestingly, the BrokerSocketDataEvent objects never get garbage
> collected -- I'm not certain if that'srelated to the segfaults or not. 
> When this app is run without any GUI, I don't see any leaks --the gc counts
> look constant. In the GUI code, I'm not explicitly maintaining a reference
> to the event objects as they're processed, so I'm at a loss to explain this
> behavior as well.

The PyQt documentation for QCustomEvent says that your code has to delete the 
event's data in order to avoid memory leaks. However, because of the way it 
is implemented, it's actually impossible to do. Try the attached patch - it 
includes updated documentation.

I suspect that this won't fix your original problem - but one thing at a time.

> I'm using Python 2.3b1, Qt 3.1.2, PyQt and SIP 3.6, gcc 3.2.2.  I'm a babe
> lost in the woods when it comes to debugging and debugging python
> extensions, so please forgive me if I've omitted something or stated
> something incorrectly.
>
> Any ideas?  Suggestions?  Am I doing something obviously wrong?  Known or
> fixed bug?  Thanks.

Phil
-------------- next part --------------
A non-text attachment was scrubbed...
Name: qevent.sip.diff
Type: text/x-diff
Size: 1504 bytes
Desc: not available
Url : http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20030617/eb5d817b/qevent.sip.bin


More information about the PyQt mailing list