summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp
diff options
context:
space:
mode:
authorArno Rehn <a.rehn@menlosystems.com>2023-06-15 17:12:02 +0200
committerArno Rehn <a.rehn@menlosystems.com>2023-06-20 09:35:15 +0200
commit855c4484693015cb6498f2183d95de1377d49898 (patch)
tree853302d072fe65a695b5e72f4df0f8e1131f7ed7 /tests/auto/corelib/thread/qpromise/tst_qpromise.cpp
parent1f6cac0da9c31b67f5cb5850ce52a4622e57b4d5 (diff)
QPromise: Propagate cancellation through failure handlers
Previously, failure handlers did not propagate cancellation. This would lead to crashes when a QPromise was cancelled without having generated any result. Subsequent continuations would be invoked and try to access the result (which was nonexistent) and then crash. This patch propagates cancellation through failure handlers to prevent subsequent continuations from being called in the first place. Fixes: QTBUG-114606 Pick-to: 6.6 Pick-to: 6.5 Change-Id: I23b28a8e70a76e1ba6416be4440360c6dbaef2a3 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Diffstat (limited to 'tests/auto/corelib/thread/qpromise/tst_qpromise.cpp')
-rw-r--r--tests/auto/corelib/thread/qpromise/tst_qpromise.cpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp b/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp
index fc1ace10cb..1002361005 100644
--- a/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp
+++ b/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp
@@ -44,6 +44,7 @@ private slots:
void cancelWhenReassigned();
void cancelWhenDestroyedWithoutStarting();
void cancelWhenDestroyedRunsContinuations();
+ void cancelWhenDestroyedWithFailureHandler(); // QTBUG-114606
void continuationsRunWhenFinished();
void finishWhenSwapped();
void cancelWhenMoved();
@@ -578,6 +579,38 @@ void tst_QPromise::cancelWhenDestroyedRunsContinuations()
}
template <typename T>
+static inline void testCancelWhenDestroyedWithFailureHandler()
+{
+ QFuture<T> future;
+ bool onFailedCalled = false;
+ bool thenCalled = false;
+ {
+ QPromise<T> promise;
+ future = promise.future();
+ future
+ .onFailed([&] () {
+ onFailedCalled = true;
+ if constexpr (!std::is_same_v<void, T>)
+ return T{};
+ })
+ .then([&] (auto&&) {
+ thenCalled = true;
+ });
+ }
+ QVERIFY(future.isFinished());
+ QVERIFY(!onFailedCalled);
+ QVERIFY(!thenCalled);
+}
+
+void tst_QPromise::cancelWhenDestroyedWithFailureHandler()
+{
+ testCancelWhenDestroyedWithFailureHandler<void>();
+ testCancelWhenDestroyedWithFailureHandler<int>();
+ testCancelWhenDestroyedWithFailureHandler<CopyOnlyType>();
+ testCancelWhenDestroyedWithFailureHandler<MoveOnlyType>();
+}
+
+template <typename T>
static inline void testContinuationsRunWhenFinished()
{
QPromise<T> promise;