diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h index 53f2326cded..5b4c929a361 100644 --- a/src/corelib/thread/qfuture_impl.h +++ b/src/corelib/thread/qfuture_impl.h @@ -732,6 +732,8 @@ void FailureHandler::run() } else { handleException(); } + } else if (parentFuture.d.isChainCanceled()) { + promise.future().cancel(); } else { QtPrivate::fulfillPromise(promise, parentFuture); } diff --git a/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp b/tests/auto/corelib/thread/qpromise/tst_qpromise.cpp index fc1ace10cbb..10023610050 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(); @@ -577,6 +578,38 @@ void tst_QPromise::cancelWhenDestroyedRunsContinuations() testCancelWhenDestroyedRunsContinuations(); } +template +static inline void testCancelWhenDestroyedWithFailureHandler() +{ + QFuture future; + bool onFailedCalled = false; + bool thenCalled = false; + { + QPromise promise; + future = promise.future(); + future + .onFailed([&] () { + onFailedCalled = true; + if constexpr (!std::is_same_v) + return T{}; + }) + .then([&] (auto&&) { + thenCalled = true; + }); + } + QVERIFY(future.isFinished()); + QVERIFY(!onFailedCalled); + QVERIFY(!thenCalled); +} + +void tst_QPromise::cancelWhenDestroyedWithFailureHandler() +{ + testCancelWhenDestroyedWithFailureHandler(); + testCancelWhenDestroyedWithFailureHandler(); + testCancelWhenDestroyedWithFailureHandler(); + testCancelWhenDestroyedWithFailureHandler(); +} + template static inline void testContinuationsRunWhenFinished() {