summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2022-03-15 00:07:37 +0100
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2022-03-17 17:14:36 +0100
commit5089db0303f4ee0ca0d7c6814e06beff119d8500 (patch)
tree90da6fe39d7502953431dac57e081727e0c3dbe7
parent440438092bc6276399cbb1bd9425227898221587 (diff)
QFuture: fix QtFuture::connect corner-cases
Connecting to nullptr, or connecting to a non-signal PMF, would result in a QFuture which would never finish. Catch these cases and handle them. Windows+MSVC for some reason fails the test. I can't entirely understand why, so I've marked it as XFAIL, with QTBUG-101761 to track it. Change-Id: I314980e7e9b7156d8cddd3b33d5cbf1d0bcd6116 Pick-to: 6.2 6.3 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
-rw-r--r--src/corelib/thread/qfuture_impl.h11
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp30
2 files changed, 41 insertions, 0 deletions
diff --git a/src/corelib/thread/qfuture_impl.h b/src/corelib/thread/qfuture_impl.h
index 22f51d755b..4c68a527da 100644
--- a/src/corelib/thread/qfuture_impl.h
+++ b/src/corelib/thread/qfuture_impl.h
@@ -880,6 +880,11 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
using ArgsType = ArgsType<Signal>;
QFutureInterface<ArgsType> promise;
promise.reportStarted();
+ if (!sender) {
+ promise.reportCanceled();
+ promise.reportFinished();
+ return promise.future();
+ }
using Connections = std::pair<QMetaObject::Connection, QMetaObject::Connection>;
auto connections = std::make_shared<Connections>();
@@ -910,6 +915,12 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
});
}
+ if (!connections->first) {
+ promise.reportCanceled();
+ promise.reportFinished();
+ return promise.future();
+ }
+
connections->second =
QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]() mutable {
QObject::disconnect(connections->first);
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index 8052ad6e27..a84b11ee68 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -3768,6 +3768,36 @@ void tst_QFuture::signalConnect()
QVERIFY(!future.isCanceled());
QVERIFY(future.isValid());
}
+
+ // Connect to nullptr
+ {
+ SenderObject *sender = nullptr;
+ auto future = QtFuture::connect(sender, &SenderObject::intArgSignal);
+ QVERIFY(future.isFinished());
+ QVERIFY(future.isCanceled());
+ QVERIFY(!future.isValid());
+ }
+
+ // Connect to non-signal
+ {
+ SenderObject sender;
+
+#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+#define EXPECT_FUTURE_CONNECT_FAIL() QEXPECT_FAIL("", "QTBUG-101761, test fails on Windows/MSVC", Continue)
+#else
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in SenderObject");
+#define EXPECT_FUTURE_CONNECT_FAIL()
+#endif
+
+ auto future = QtFuture::connect(&sender, &SenderObject::emitNoArg);
+ EXPECT_FUTURE_CONNECT_FAIL();
+ QVERIFY(future.isFinished());
+ EXPECT_FUTURE_CONNECT_FAIL();
+ QVERIFY(future.isCanceled());
+ EXPECT_FUTURE_CONNECT_FAIL();
+ QVERIFY(!future.isValid());
+#undef EXPECT_FUTURE_CONNECT_FAIL
+ }
}
void tst_QFuture::waitForFinished()