diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2013-02-27 15:48:17 -0800 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-02-28 23:43:46 +0100 |
commit | 50d3a2917e37cd173f373a83542314002b2ab6c7 (patch) | |
tree | 8f686b6790cfe6385a07199c02f156f703729620 /tests/auto | |
parent | ebfd85a499a4382ace09d443b1f35cd6b1848af6 (diff) |
Fix Q_GLOBAL_STATIC support for exceptions
The problem was that the HolderBase destructor was getting called after
the contained type's constructor threw an exception, as is required by
RAII semantics (the base was fully initialized, so it had to be
destroyed). That was required because we want to return a non-null
pointer from operator() during destruction and return null after
destruction, to keep compatibility with Qt 4.
The solution is to only set the guard to Destroyed only if it is already
at value Initialized. This way, if the HolderBase destructor is run as
part of the stack unwinding, it knows that the construction did not
complete.
Change-Id: I9849b43ed7112bf9e70861b48a56a924c286617e
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp index b9aa70fe80..131b37f821 100644 --- a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp +++ b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp @@ -50,6 +50,7 @@ private Q_SLOTS: void api(); void constVolatile(); void exception(); + void threadedException(); void threadStressTest(); void afterDestruction(); }; @@ -107,6 +108,11 @@ struct ThrowingType { static QBasicAtomicInt constructedCount; static QBasicAtomicInt destructedCount; + ThrowingType() + { + throw 0; + } + ThrowingType(QBasicAtomicInt &throwControl) { constructedCount.ref(); @@ -115,12 +121,28 @@ struct ThrowingType } ~ThrowingType() { destructedCount.ref(); } }; + QBasicAtomicInt ThrowingType::constructedCount = Q_BASIC_ATOMIC_INITIALIZER(0); QBasicAtomicInt ThrowingType::destructedCount = Q_BASIC_ATOMIC_INITIALIZER(0); +Q_GLOBAL_STATIC(ThrowingType, throwingGS) +void tst_QGlobalStatic::exception() +{ + bool exceptionCaught = false; + try { + throwingGS(); + } catch (int) { + exceptionCaught = true; + } + QVERIFY(exceptionCaught); + QCOMPARE(Q_QGS_throwingGS::guard.load(), 0); + QVERIFY(!throwingGS.exists()); + QVERIFY(!throwingGS.isDestroyed()); +} + QBasicAtomicInt exceptionControlVar = Q_BASIC_ATOMIC_INITIALIZER(1); Q_GLOBAL_STATIC_WITH_ARGS(ThrowingType, exceptionGS, (exceptionControlVar)) -void tst_QGlobalStatic::exception() +void tst_QGlobalStatic::threadedException() { if (exceptionControlVar.load() != 1) QSKIP("This test cannot be run more than once"); |