QtFuture::connect: disconnect signals first

During reportFinished we may call a continuation which might end up
triggering one of the signals.

Change-Id: I19546fcca12be71cd536e4287eb5eddd9d236830
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit bb85831e4de5e2c4951a0c40003ccf36f57cbd93)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Mårten Nordheim 2021-04-07 14:27:21 +02:00 committed by Qt Cherry-pick Bot
parent 33ae5d2145
commit 9923a90100
2 changed files with 26 additions and 7 deletions

View File

@ -807,34 +807,34 @@ static QFuture<ArgsType<Signal>> connect(Sender *sender, Signal signal)
if constexpr (std::is_void_v<ArgsType>) {
connections->first =
QObject::connect(sender, signal, sender, [promise, connections]() mutable {
promise.reportFinished();
QObject::disconnect(connections->first);
QObject::disconnect(connections->second);
promise.reportFinished();
});
} else if constexpr (QtPrivate::isTupleV<ArgsType>) {
connections->first = QObject::connect(sender, signal, sender,
[promise, connections](auto... values) mutable {
promise.reportResult(std::make_tuple(values...));
promise.reportFinished();
QObject::disconnect(connections->first);
QObject::disconnect(connections->second);
promise.reportResult(std::make_tuple(values...));
promise.reportFinished();
});
} else {
connections->first = QObject::connect(sender, signal, sender,
[promise, connections](ArgsType value) mutable {
promise.reportResult(value);
promise.reportFinished();
QObject::disconnect(connections->first);
QObject::disconnect(connections->second);
promise.reportResult(value);
promise.reportFinished();
});
}
connections->second =
QObject::connect(sender, &QObject::destroyed, sender, [promise, connections]() mutable {
promise.reportCanceled();
promise.reportFinished();
QObject::disconnect(connections->first);
QObject::disconnect(connections->second);
promise.reportCanceled();
promise.reportFinished();
});
return promise.future();

View File

@ -3228,6 +3228,25 @@ void tst_QFuture::signalConnect()
QVERIFY(future.isCanceled());
QVERIFY(!future.isValid());
}
// Signal emitted, causing Sender to be destroyed
{
SenderObject *sender = new SenderObject();
auto future = QtFuture::connect(sender, &SenderObject::intArgSignal);
future.then([sender](int) {
// Scenario: Sender no longer needed, so it's deleted
delete sender;
});
QSignalSpy spy(sender, &SenderObject::destroyed);
emit sender->intArgSignal(5);
spy.wait();
QVERIFY(future.isFinished());
QVERIFY(!future.isCanceled());
QVERIFY(future.isValid());
}
}
void tst_QFuture::waitForFinished()