Details
-
Bug
-
Resolution: Done
-
P2: Important
-
6.4.0 Beta2
-
None
-
-
8
-
24dedaeaa1 (qt/qtbase/dev) ee349ffba0 (qt/qtbase/6.4) ee349ffba0 (qt/tqtc-qtbase/6.4) 24dedaeaa1 (qt/tqtc-qtbase/dev) 0006a401a4 (qt/tqtc-qtbase/6.2) 018d013181 (qt/qtbase/6.3) 018d013181 (qt/tqtc-qtbase/6.3)
-
Foundation Sprint 65, Foundation Sprint 66
Description
I was able to create a mini application that shows the behavior. I've isolated the behavior that causes problems to it's bare minimums that kind of resembles the structure how I use QFuture in my application.
Original description below.
#include <QGuiApplication> #include <QTimer> #include <QPromise> #include <QFuture> QFuture<bool> returnTrueAsync() { QTimer* timer = new QTimer(); auto future = QtFuture::connect(timer, &QTimer::timeout) .then([timer](){ timer->deleteLater(); return true; }); timer->start(1000); return future; } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QtFuture::makeReadyFuture(true) .then([](bool){ return returnTrueAsync(); }) .unwrap() .then([](bool list){ return QtFuture::makeReadyFuture(true) .then([](bool) { // this then is important for the bug return true; }); }) .unwrap() // this unwrap is important for the bug .then([](bool list){ qDebug() << "Usually does not reach this"; qDebug() << "Usually there is an access violation exception before reaching this point"; }); return app.exec(); }
ORIGINAL CONTENT OF TICKET:
In my application I use the new QFuture::unwrap() a lot. In some particular cases the whole application hangs on a call to QFutureInterfaceBase::isChainCanceled() somewhere down the backtrace. I cannot isolate this issue but it's quite easy to reproduce in my application.
In my current debugger view I see that the pointer to one of the "d->parentData" pointer is pointing to corrupt data. It's probably pointing to an earlier parent that has been freed or was never pointing to correct data.
Also sometimes the "d->parentData" points to another parentData which again points to the first parentData. Thus creating a inifinite loop. One has state (Started|Finished) the other ("Pending"). This never ends the loop in isChainCanceled().
The bug does not happen when running inside gdb or valgrind. So it looks like some memory corruption bug.
There is also a probability that I do something stupid in my code.
I have added a screenshot of the most (in my opinion) useful information I could find in the debugger view, right during one of the infinite loops.
The piece of code that misbehaves looks like this:
void RetQueueViewController::loadQueuesImpl() { setState(Loading); authenticationService()->getValidApiToken() .then([this](QString apiToken){ return zorgstandApiClient()->getZorgstandWidgetQueues(apiToken, widgetId()); // returns QFuture<QList<RetZorgstandQueueDto*>> }) .unwrap() // The then(...) below never gets invoked .then([this](QList<RetZorgstandQueueDto*> queues){ clearQueues(); for(auto queue : queues){ addQueues(queue); } }) .onFailed([this](){ setState(Error); qDebug() << "Failed to fetch queues"; }) .then([this](){ if(state() == Loading){ if(queues().length() == 0){ setState(Error); return; } if(queues().length() == 1){ setQueue(queues().at(0).value<RetZorgstandQueueDto*>()); setState(Queue); return; } setState(Select); return; } }); // Method ends here, doesn't wait for finished. The parent object lives long and has not been destroyed while this happens. }
Attachments
Issue Links
- is duplicated by
-
QTBUG-108498 QFuture (makeReadyFuture) hangs if returned from function
- Closed
- relates to
-
QTBUG-106083 QFuture::then(QObject *context, Function &&function) throws "read access violation" when used in chained QFuture
- Closed