From c47cd8f01ea5d3f2a6d0ea73572d9735947919a0 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 11 Oct 2011 15:51:58 +0100 Subject: Symbian - fix deleteLater not working from RunL deleteLater stores the loop level in the deferred delete event to prevent the object being deleted by a nested event loop. However as symbian active object RunL functions are called directly from the active scheduler, the loop level is incorrect at that point. (It is normally set by QCoreApplication::notifyInternal) To solve this, the loop level is adjusted before calling RunIfReady so that it is correct during RunL functions. It is then adjusted back for the specific active objects in the event dispatcher that call into QCoreApplication - sendPostedEvents, sendEvent. Task-number: QTBUG-21928 Reviewed-by: mread --- src/corelib/kernel/qeventdispatcher_symbian.cpp | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 5e2bc4f..b796728 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -61,6 +61,24 @@ QT_BEGIN_NAMESPACE #define NULLTIMER_PRIORITY CActive::EPriorityLow #define COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY CActive::EPriorityIdle +class Incrementer { + int &variable; +public: + inline Incrementer(int &variable) : variable(variable) + { ++variable; } + inline ~Incrementer() + { --variable; } +}; + +class Decrementer { + int &variable; +public: + inline Decrementer(int &variable) : variable(variable) + { --variable; } + inline ~Decrementer() + { ++variable; } +}; + static inline int qt_pipe_write(int socket, const char *data, qint64 len) { return ::write(socket, data, len); @@ -830,6 +848,8 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla #endif while (1) { + //native active object callbacks are logically part of the event loop, so inc nesting level + Incrementer inc(d->threadData->loopLevel); if (block) { // This is where Qt will spend most of its time. CActiveScheduler::Current()->WaitForAnyRequest(); @@ -894,6 +914,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla void QEventDispatcherSymbian::timerFired(int timerId) { + Q_D(QAbstractEventDispatcher); QHash::iterator i = m_timerList.find(timerId); if (i == m_timerList.end()) { // The timer has been deleted. Ignore this event. @@ -912,6 +933,8 @@ void QEventDispatcherSymbian::timerFired(int timerId) m_insideTimerEvent = true; QTimerEvent event(timerInfo->timerId); + //undo the added nesting level around RunIfReady, since Qt's event system also nests + Decrementer dec(d->threadData->loopLevel); QCoreApplication::sendEvent(timerInfo->receiver, &event); m_insideTimerEvent = oldInsideTimerEventValue; @@ -922,6 +945,7 @@ void QEventDispatcherSymbian::timerFired(int timerId) void QEventDispatcherSymbian::socketFired(QSocketActiveObject *socketAO) { + Q_D(QAbstractEventDispatcher); if (m_noSocketEvents) { m_deferredSocketEvents.append(socketAO); return; @@ -929,6 +953,8 @@ void QEventDispatcherSymbian::socketFired(QSocketActiveObject *socketAO) QEvent e(QEvent::SockAct); socketAO->m_inSocketEvent = true; + //undo the added nesting level around RunIfReady, since Qt's event system also nests + Decrementer dec(d->threadData->loopLevel); QCoreApplication::sendEvent(socketAO->m_notifier, &e); socketAO->m_inSocketEvent = false; @@ -943,6 +969,7 @@ void QEventDispatcherSymbian::socketFired(QSocketActiveObject *socketAO) void QEventDispatcherSymbian::wakeUpWasCalled() { + Q_D(QAbstractEventDispatcher); // The reactivation should happen in RunL, right before the call to this function. // This is because m_wakeUpDone is the "signal" that the object can be completed // once more. @@ -952,6 +979,8 @@ void QEventDispatcherSymbian::wakeUpWasCalled() // the sendPostedEvents was done, but before the object was ready to be completed // again. This could deadlock the application if there are no other posted events. m_wakeUpDone.fetchAndStoreOrdered(0); + //undo the added nesting level around RunIfReady, since Qt's event system also nests + Decrementer dec(d->threadData->loopLevel); sendPostedEvents(); } -- cgit v0.12