diff options
author | Carlos Manuel Duclos Vergara <carlos.duclos@nokia.com> | 2010-08-18 15:59:04 (GMT) |
---|---|---|
committer | Carlos Manuel Duclos Vergara <carlos.duclos@nokia.com> | 2010-08-18 16:04:01 (GMT) |
commit | 8dd8db250d92521fda619bdcf3e1c859b37b2da0 (patch) | |
tree | a020322262504fe0cbc3bcd6f7c620bc41caea3f | |
parent | 8e7fb343372acd0bc5fe04db7a5c5542541d4538 (diff) | |
download | Qt-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.cpp | 24 | ||||
-rw-r--r-- | tests/auto/qapplication/modal/base.cpp | 21 | ||||
-rw-r--r-- | tests/auto/qapplication/modal/base.h | 23 | ||||
-rw-r--r-- | tests/auto/qapplication/modal/main.cpp | 11 | ||||
-rw-r--r-- | tests/auto/qapplication/modal/modal.pro | 8 | ||||
-rw-r--r-- | tests/auto/qapplication/qapplication.pro | 1 | ||||
-rw-r--r-- | tests/auto/qapplication/tst_qapplication.cpp | 18 |
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[]) { |