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:
parent
33ae5d2145
commit
9923a90100
@ -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();
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user