QEventLoop + QNetworkRequest = dead lock
-
In Qt6, I've found that the bundle identified in the topic title sometimes has a dead lock. I have never noticed this before.
QNetworkRequest request(url); auto reply = networkManager.post(request, multiPart); QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec();
Pure classic combination for some REST API requests.
As it turned out, in some scenarios reply does not emit the QNetworkReply::finished signal and the thread hangs forever.
I found a not-so-pretty but workable solution:
#define REQUEST_DEADLOCK_SAVER \ QTimer timer;\ timer.setSingleShot(true);\ timer.setInterval(REQUEST_TIMEOUT);\ QObject::connect(&timer, &QTimer::timeout, [&loop](){\ qWarning() << "Network request dropped by timeout";\ loop.quit();\ });\ QObject::connect(reply, &QNetworkReply::finished, &timer, &QTimer::stop);\ timer.start();
Use it like this:
QNetworkRequest request(url); auto reply = networkManager.post(request, multiPart) : this->aManager.get(request); QEventLoop loop; REQUEST_DEADLOCK_SAVER // <-------- solution QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec();
Has anyone encountered a similar problem?
-
@acetone said in QEventLoop + QNetworkRequest = dead lock:
As it turned out, in some scenarios reply does not emit the QNetworkReply::finished signal
Have you Googled for
QNetworkReply::finished signal not emitted
and read through the various hits? -
@JonB Unfortunately, I can't find the answer in my case: I don't have infinity loops, all objects exist at the moment of request and its completion. The code used to work on Qt5 and now works on Qt6, but can go deadlocked after a few hours or days of uptime. It took me a long time to realize that this is where the hangup was happening)
-
@acetone said in QEventLoop + QNetworkRequest = dead lock:
@jeremy_k said in QEventLoop + QNetworkRequest = dead lock:
Why use a nested event loop?
To create a blocking operation in a context where further action only makes sense after receiving a response from the server.
Don't do that. Qt is heavily tested in the default configuration, where there is a single event loop and no significant blocking operations. Bugs do occur, but they're found and fixed relatively rapidly on the common path. Code that subverts that path has a tendency to find broken corner cases.
If you need a "blocking" operation, create a signal that indicates that the operation has completed, and allow everything else that relies on the event loop to continue as normal.
-