summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlos Manuel Duclos Vergara <carlos.duclos@nokia.com>2010-08-18 15:59:04 (GMT)
committerCarlos Manuel Duclos Vergara <carlos.duclos@nokia.com>2010-08-18 16:04:01 (GMT)
commit8dd8db250d92521fda619bdcf3e1c859b37b2da0 (patch)
treea020322262504fe0cbc3bcd6f7c620bc41caea3f
parent8e7fb343372acd0bc5fe04db7a5c5542541d4538 (diff)
downloadQt-8dd8db250d92521fda619bdcf3e1c859b37b2da0.zip
Qt-8dd8db250d92521fda619bdcf3e1c859b37b2da0.tar.gz
Qt-8dd8db250d92521fda619bdcf3e1c859b37b2da0.tar.bz2
Crash in QWidgetPrivate::init on QApplication::quit() using a modal dialog on Mac
The problem was the order of deletion in the destructor. To autotest this I create an application, start a modal dialog and then quit the application. The fix was contributed by a customer. Task-number: QTBUG-12673 Reviewed-by: Olivier Goffart
-rw-r--r--src/gui/kernel/qapplication.cpp24
-rw-r--r--tests/auto/qapplication/modal/base.cpp21
-rw-r--r--tests/auto/qapplication/modal/base.h23
-rw-r--r--tests/auto/qapplication/modal/main.cpp11
-rw-r--r--tests/auto/qapplication/modal/modal.pro8
-rw-r--r--tests/auto/qapplication/qapplication.pro1
-rw-r--r--tests/auto/qapplication/tst_qapplication.cpp18
7 files changed, 94 insertions, 12 deletions
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index e164baf..3d3a749 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -1055,6 +1055,18 @@ QApplication::~QApplication()
QApplicationPrivate::is_app_closing = true;
QApplicationPrivate::is_app_running = false;
+ // delete all widgets
+ if (QWidgetPrivate::allWidgets) {
+ QWidgetSet *mySet = QWidgetPrivate::allWidgets;
+ QWidgetPrivate::allWidgets = 0;
+ for (QWidgetSet::ConstIterator it = mySet->constBegin(); it != mySet->constEnd(); ++it) {
+ register QWidget *w = *it;
+ if (!w->parent()) // window
+ w->destroy(true, true);
+ }
+ delete mySet;
+ }
+
delete qt_desktopWidget;
qt_desktopWidget = 0;
@@ -1075,18 +1087,6 @@ QApplication::~QApplication()
delete QWidgetPrivate::mapper;
QWidgetPrivate::mapper = 0;
- // delete all widgets
- if (QWidgetPrivate::allWidgets) {
- QWidgetSet *mySet = QWidgetPrivate::allWidgets;
- QWidgetPrivate::allWidgets = 0;
- for (QWidgetSet::ConstIterator it = mySet->constBegin(); it != mySet->constEnd(); ++it) {
- register QWidget *w = *it;
- if (!w->parent()) // window
- w->destroy(true, true);
- }
- delete mySet;
- }
-
delete QApplicationPrivate::app_pal;
QApplicationPrivate::app_pal = 0;
delete QApplicationPrivate::sys_pal;
diff --git a/tests/auto/qapplication/modal/base.cpp b/tests/auto/qapplication/modal/base.cpp
new file mode 100644
index 0000000..d3a7de6
--- /dev/null
+++ b/tests/auto/qapplication/modal/base.cpp
@@ -0,0 +1,21 @@
+#include "base.h"
+
+base::base(QWidget *parent) :
+ QWidget(parent)
+{
+ m_timer = new QTimer(this);
+ m_modalStarted = false;
+ m_timer->setSingleShot(false);
+ connect(m_timer, SIGNAL(timeout()), this, SLOT(periodicTimer()));
+ m_timer->start(5000);
+}
+
+void base::periodicTimer()
+{
+ if(m_modalStarted)
+ exit(0);
+ m_modalDialog = new QDialog(this);
+ m_modalDialog->setModal(true);
+ m_modalDialog->show();
+ m_modalStarted = true;
+}
diff --git a/tests/auto/qapplication/modal/base.h b/tests/auto/qapplication/modal/base.h
new file mode 100644
index 0000000..ebf1198
--- /dev/null
+++ b/tests/auto/qapplication/modal/base.h
@@ -0,0 +1,23 @@
+#ifndef BASE_H
+#define BASE_H
+
+#include <QWidget>
+#include <QTimer>
+#include <QDialog>
+
+class base : public QWidget
+{
+Q_OBJECT
+ QTimer *m_timer;
+ bool m_modalStarted;
+ QDialog *m_modalDialog;
+public:
+ explicit base(QWidget *parent = 0);
+
+signals:
+
+public slots:
+ void periodicTimer();
+};
+
+#endif // BASE_H
diff --git a/tests/auto/qapplication/modal/main.cpp b/tests/auto/qapplication/modal/main.cpp
new file mode 100644
index 0000000..e1d39cf
--- /dev/null
+++ b/tests/auto/qapplication/modal/main.cpp
@@ -0,0 +1,11 @@
+#include <QtGui>
+
+#include <QApplication>
+#include "base.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ base *b = new base();
+ return app.exec();
+}
diff --git a/tests/auto/qapplication/modal/modal.pro b/tests/auto/qapplication/modal/modal.pro
new file mode 100644
index 0000000..836f6ff
--- /dev/null
+++ b/tests/auto/qapplication/modal/modal.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+SOURCES += main.cpp \
+ base.cpp
+DESTDIR = ./
+HEADERS += base.h
diff --git a/tests/auto/qapplication/qapplication.pro b/tests/auto/qapplication/qapplication.pro
index 7814ad3..becc6c6 100644
--- a/tests/auto/qapplication/qapplication.pro
+++ b/tests/auto/qapplication/qapplication.pro
@@ -1,6 +1,7 @@
TEMPLATE = subdirs
SUBDIRS = test \
desktopsettingsaware \
+ modal \
wincmdline
diff --git a/tests/auto/qapplication/tst_qapplication.cpp b/tests/auto/qapplication/tst_qapplication.cpp
index 1a38070..91ae921 100644
--- a/tests/auto/qapplication/tst_qapplication.cpp
+++ b/tests/auto/qapplication/tst_qapplication.cpp
@@ -146,6 +146,7 @@ private slots:
void symbianNeedForTraps();
void symbianLeaveThroughMain();
+ void qtbug_12673();
};
class EventSpy : public QObject
@@ -2239,6 +2240,23 @@ void tst_QApplication::symbianLeaveThroughMain()
#endif
}
+void tst_QApplication::qtbug_12673()
+{
+#ifdef Q_OS_SYMBIAN
+ QSKIP("This might not make sense in Symbian, but since I do not know how to test it I'll just skip it for now.", SkipAll);
+#else
+ QProcess testProcess;
+ QStringList arguments;
+#ifdef Q_OS_MAC
+ testProcess.start("modal/modal.app", arguments);
+#else
+ testProcess.start("modal/modal", arguments);
+#endif
+ QVERIFY(testProcess.waitForFinished(20000));
+ QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit);
+#endif // Q_OS_SYMBIAN
+}
+
//QTEST_APPLESS_MAIN(tst_QApplication)
int main(int argc, char *argv[])
{