Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-111398

QNetworkAccessManager hangs indefinitely when loading a corrupted cache file

    XMLWordPrintable

Details

    • Bug
    • Resolution: Duplicate
    • Not Evaluated
    • None
    • 6.4.2
    • None

    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();
      } 
      1. 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.
      2. 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
      1. 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.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            manordheim Mårten Nordheim
            bclement Basile Clement
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes