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
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
(cherry picked from commit 5089db0303f4ee0ca0d7c6814e06beff119d8500)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Giuseppe D'Angelo 2022-03-15 00:07:37 +01:00 committed by Qt Cherry-pick Bot
parent 7c0e2c19dd
commit c08842daea
2 changed files with 41 additions and 0 deletions

View File

@ -832,6 +832,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>();
@ -862,6 +867,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);

View File

@ -3667,6 +3667,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()