summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorGareth Stockwell <ext-gareth.stockwell@nokia.com>2011-08-11 12:58:23 (GMT)
committerGareth Stockwell <ext-gareth.stockwell@nokia.com>2011-08-31 09:17:34 (GMT)
commit298d7a2032c0c6de06c82afc8e9f7356cb5d7840 (patch)
treeb7dc09a7f0934920c6d03c8e2f383347b464f6d9 /src/gui/kernel
parent91096126440aafba22aeb9307cb72135b3156a4c (diff)
downloadQt-298d7a2032c0c6de06c82afc8e9f7356cb5d7840.zip
Qt-298d7a2032c0c6de06c82afc8e9f7356cb5d7840.tar.gz
Qt-298d7a2032c0c6de06c82afc8e9f7356cb5d7840.tar.bz2
Prevent leakage of native window handles
On Symbian, reparenting a native widget causes its native window, and those of all its ancestors, to be destroyed and recreated. Because native window handles cannot be destroyed from the context of CONE event handlers, the destruction is delayed until after control flow returns to the event loop (see QTBUG-4664). However, the pending-destruction native windows are leaked if either of the following happens: a) The application never returns to the event loop. While unlikely in a real app, this situation does happen in Qt autotests, causing a crash in tst_qwidget due to leakage from tst_QWidget::reparentCausesChildWinIdChange(). b) A subsequent reparenting event occurs before control returns to the event loop. This patch prevents the leak by storing the pending-destruction native window handle(s) in a member QList, rather than on the stack as parameters to QWidgetPrivate::_q_delayedDestroy(WId). Task-number: QT-5135 Reviewed-by: Jani Hautakangas
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/qwidget.cpp10
-rw-r--r--src/gui/kernel/qwidget.h2
-rw-r--r--src/gui/kernel/qwidget_p.h3
-rw-r--r--src/gui/kernel/qwidget_s60.cpp8
4 files changed, 14 insertions, 9 deletions
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index ac8e690..8e8266c 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -334,6 +334,10 @@ QWidgetPrivate::QWidgetPrivate(int version)
QWidgetPrivate::~QWidgetPrivate()
{
+#ifdef Q_OS_SYMBIAN
+ _q_cleanupWinIds();
+#endif
+
if (widgetItem)
widgetItem->wid = 0;
@@ -12561,9 +12565,11 @@ void QWidget::clearMask()
*/
#ifdef Q_OS_SYMBIAN
-void QWidgetPrivate::_q_delayedDestroy(WId winId)
+void QWidgetPrivate::_q_cleanupWinIds()
{
- delete winId;
+ foreach (WId wid, widCleanupList)
+ delete wid;
+ widCleanupList.clear();
}
#endif
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 2c89405..2f8545e 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -787,7 +787,7 @@ private:
Q_DISABLE_COPY(QWidget)
Q_PRIVATE_SLOT(d_func(), void _q_showIfNotHidden())
#ifdef Q_OS_SYMBIAN
- Q_PRIVATE_SLOT(d_func(), void _q_delayedDestroy(WId winId))
+ Q_PRIVATE_SLOT(d_func(), void void _q_cleanupWinIds())
#endif
QWidgetData *data;
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index c00b8ed..e30497c 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -409,7 +409,7 @@ public:
#ifdef Q_OS_SYMBIAN
void setSoftKeys_sys(const QList<QAction*> &softkeys);
void activateSymbianWindow(WId wid = 0);
- void _q_delayedDestroy(WId winId);
+ void _q_cleanupWinIds();
#endif
void raise_sys();
@@ -889,6 +889,7 @@ public:
void s60UpdateIsOpaque();
void reparentChildren();
void registerTouchWindow();
+ QList<WId> widCleanupList;
#endif
};
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index 5630706..3c2d63c 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -58,9 +58,7 @@
#endif
// This is necessary in order to be able to perform delayed invocation on slots
-// which take arguments of type WId. One example is
-// QWidgetPrivate::_q_delayedDestroy, which is used to delay destruction of
-// CCoeControl objects until after the CONE event handler has finished running.
+// which take arguments of type WId.
Q_DECLARE_METATYPE(WId)
// Workaround for the fact that S60 SDKs 3.x do not contain the akntoolbar.h
@@ -476,8 +474,8 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
// Delay deletion of the control in case this function is called in the
// context of a CONE event handler such as
// CCoeControl::ProcessPointerEventL
- QMetaObject::invokeMethod(q, "_q_delayedDestroy",
- Qt::QueuedConnection, Q_ARG(WId, destroyw));
+ widCleanupList << destroyw;
+ QMetaObject::invokeMethod(q, "_q_cleanupWinIds", Qt::QueuedConnection);
}
if (q->testAttribute(Qt::WA_AcceptTouchEvents))