diff options
author | Christian Strømme <christian.stromme@qt.io> | 2016-08-18 11:44:45 +0200 |
---|---|---|
committer | Christian Stromme <christian.stromme@qt.io> | 2016-08-23 14:55:49 +0000 |
commit | 5e3f770ad5e47f296b4782c0b6c5b03162027500 (patch) | |
tree | ef38b8ec77b976edfb7cc28e41450a6e6df8fd3a | |
parent | 449390c3a5f3a91e3895cbba0a583386e93366b7 (diff) |
Fix problem with exception reporting in QFuture::waitForResult()
This fixes a problem that occurs when a task, that is run synchronously,
throws an exception. If that happened, then the exception would not be
re-thrown, because of an early return.
Task-number: QTBUG-54831
Change-Id: Ic70c5b810ec6adce6e62bfd6832ba9f170b13a7f
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@theqtcompany.com>
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 11 | ||||
-rw-r--r-- | tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp | 37 |
2 files changed, 42 insertions, 6 deletions
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp index 60155c96fd..2fe038165b 100644 --- a/src/corelib/thread/qfutureinterface.cpp +++ b/src/corelib/thread/qfutureinterface.cpp @@ -299,12 +299,11 @@ void QFutureInterfaceBase::waitForResult(int resultIndex) lock.relock(); - if (!(d->state & Running)) - return; - - const int waitIndex = (resultIndex == -1) ? INT_MAX : resultIndex; - while ((d->state & Running) && d->internal_isResultReadyAt(waitIndex) == false) - d->waitCondition.wait(&d->m_mutex); + if (d->state & Running) { + const int waitIndex = (resultIndex == -1) ? INT_MAX : resultIndex; + while ((d->state & Running) && d->internal_isResultReadyAt(waitIndex) == false) + d->waitCondition.wait(&d->m_mutex); + } d->m_exceptionStore.throwPossibleException(); } diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp index 8ffe4d8dfe..7e057f3bcf 100644 --- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp +++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp @@ -440,6 +440,19 @@ int throwFunctionReturn() return 0; } +class SlowTask : public QRunnable +{ +public: + static QAtomicInt cancel; + void run() Q_DECL_OVERRIDE { + int iter = 60; + while (--iter && !cancel.load()) + QThread::currentThread()->msleep(25); + } +}; + +QAtomicInt SlowTask::cancel; + void tst_QtConcurrentRun::exceptions() { QThreadPool pool; @@ -480,6 +493,30 @@ void tst_QtConcurrentRun::exceptions() } if (!caught) QFAIL("did not get exception"); + + caught = false; + try { + QtConcurrent::run(&pool, throwFunctionReturn).result(); + } catch (QException &) { + caught = true; + } + QVERIFY2(caught, "did not get exception"); + + // Force the task to be run on this thread. + caught = false; + QThreadPool shortPool; + shortPool.setMaxThreadCount(1); + SlowTask *st = new SlowTask(); + try { + shortPool.start(st); + QtConcurrent::run(&shortPool, throwFunctionReturn).result(); + } catch (QException &) { + caught = true; + } + + SlowTask::cancel.store(true); + + QVERIFY2(caught, "did not get exception"); } #endif |