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:
parent
7c0e2c19dd
commit
c08842daea
@ -832,6 +832,11 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
|
|||||||
using ArgsType = ArgsType<Signal>;
|
using ArgsType = ArgsType<Signal>;
|
||||||
QFutureInterface<ArgsType> promise;
|
QFutureInterface<ArgsType> promise;
|
||||||
promise.reportStarted();
|
promise.reportStarted();
|
||||||
|
if (!sender) {
|
||||||
|
promise.reportCanceled();
|
||||||
|
promise.reportFinished();
|
||||||
|
return promise.future();
|
||||||
|
}
|
||||||
|
|
||||||
using Connections = std::pair<QMetaObject::Connection, QMetaObject::Connection>;
|
using Connections = std::pair<QMetaObject::Connection, QMetaObject::Connection>;
|
||||||
auto connections = std::make_shared<Connections>();
|
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 =
|
connections->second =
|
||||||
QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]() mutable {
|
QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]() mutable {
|
||||||
QObject::disconnect(connections->first);
|
QObject::disconnect(connections->first);
|
||||||
|
@ -3667,6 +3667,36 @@ void tst_QFuture::signalConnect()
|
|||||||
QVERIFY(!future.isCanceled());
|
QVERIFY(!future.isCanceled());
|
||||||
QVERIFY(future.isValid());
|
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()
|
void tst_QFuture::waitForFinished()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user