Details
-
Bug
-
Resolution: Fixed
-
P1: Critical
-
6.4.2
-
None
-
8
-
a6776de0c (dev), e5f295c8a (dev), de47bc2c1 (6.5), cfb879565 (6.5), 9c27e1659 (6.4), c3dd38cf8 (tqtc/lts-6.2), 45b691f02 (6.4), 8755c0561 (tqtc/lts-6.2)
-
Foundation Sprint 77
Description
When making a cached request for which there is a corrupted cache file (in particular a cache file with empty contents), the request never terminates.
Steps to reproduce
The issue can be reproduced with the following MWE:
#include <QtCore> #include <QtNetwork>int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QNetworkAccessManager nam; QObject::connect(&nam, &QNetworkAccessManager::finished, &nam, [](QNetworkReply *reply) { QTextStream(stdout) << "Got a reply: " << reply->url().toDisplayString() << Qt::endl; reply->deleteLater(); }); auto cache = new QNetworkDiskCache; cache->setCacheDirectory("/tmp/qtcache"); nam.setCache(cache); nam.setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); QNetworkRequest req(QUrl("https://www.qt.io/hubfs/Quality_Assurance.png")); auto reply = nam.get(req); QObject::connect(reply, &QNetworkReply::finished, &a, &QCoreApplication::quit); return a.exec(); }
- Run the code once to download a cached copy of https://www.qt.io/hubfs/Quality_Assurance.png (this is just an URL that has proper caching headers set) in `/tmp/qtcache`. It should print `Got a reply: https://www.qt.io/hubfs/Quality_Assurance.png` then exit cleanly.
- Manually corrupt the cache file that got created in `/tmp/qtcache/data8/` to only keep the first line (the exact name of the cache file may be different on your machine):
$ sed -i -n '1p' /tmp/qtcache/data8/6/3ia6ms7v.d
- Run the code again. It now never prints the `Got a reply` message and hangs forever.
Additional Information
I tracked this down to `QNetworkReplyHttpImplPrivate::_q_cacheLoadReadyRead` failing early because `cacheLoadDevice->bytesAvailable()` is `0` in that case, but `_q_cacheLoadReadyRead` is never called again afterwards.
Note that QNetworkDiskCache seems to be using atomic rename in `QNetworkDiskCachePrivate::storeItem` so from my understanding it should not be able to create such corrupted/partial cache files yet we saw it happen here.