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

QNetworkAccessManager hangs indefinitely when loading a corrupted cache file

    XMLWordPrintable

Details

    • 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();
      } 
      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

        For Gerrit Dashboard: QTBUG-111397
        # Subject Branch Project Status CR V

        Activity

          People

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

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews