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

QWebEngineUrlRequestJob::reply() does not support a QIODevice that cannot be read completely instantly

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P1: Critical
    • 6.2.6, 6.5.0 Beta1
    • 5.15.10, 6.3.1
    • WebEngine
    • None
    • Linux/X11
    • aefd389bfd (qt/qtwebengine/dev) d72c6f2c65 (qt/qtwebengine/6.3) d72c6f2c65 (qt/tqtc-qtwebengine/6.3) aefd389bfd (qt/tqtc-qtwebengine/dev) e0c0f791a1 (qt/qtwebengine/6.4) e0c0f791a1 (qt/tqtc-qtwebengine/6.4) d72c6f2c65 (qt/tqtc-qtwebengine/6.2)

    Description

      When the data of a QIODevice passed to QWebEngineUrlRequestJob::reply() is not ready to be read, the job finishes and is destroyed as soon as QIODevice::atEnd() returns true. For a QNetworkReply object returned from QNetworkAccessManager::get(), QIODevice::atEnd() returns true until the data is downloaded. So passing a network reply to QWebEngineUrlRequestJob::reply() results in the "Operation canceled" QNetworkReply error and a blank web page.

      Unfortunately, making QIODevice::atEnd() return true only when all data has arrived and was read, does not work well either. In this case, QIODevice::readData() (which returns 0 while the data is unavailable) and QIODevice::atEnd() (which returns false) are called one after another in an endless loop, which keeps 2-3 CPU cores busy.

       The intention of relevant code in URLRequestCustomJobDelegate::reply() and URLRequestCustomJobProxy::readyRead() appears to be: read data only when it becomes available by connecting to &QIODevice::readyRead(). So I think this behavior hasn't been tested properly and is wrong by accident.

       The bug can be reproduced by printing debug output in StreamingIODevice::readData() in tst_qwebengineprofile.cpp. There is a great deal of (probably) unintended calls to StreamingIODevice::readData(), which repeatedly return 0.

       Before looking for an existing Qt WebEngine test I wrote a class similar to StreamingIODevice for testing. Attached a complete example QWebEngineUrlSchemeHandler-test.zip to this bug. Without command line arguments, the example reproduces repeating readyRead() and atEnd() calls. When an URL is passed as the first command line argument, the example reproduces the "Operation canceled" QNetworkReply error. When a number X is passed as the first command line argument (X=30 works well), QIODevice::readData() calls QThread::msleep(X) before returning 0. Such sleeping is my current preferred workaround for this bug. Comments in the example cpp file explain why an alternative condition variable workaround doesn't work well.

       An answer to https://stackoverflow.com/questions/44021082/implementing-a-custom-qwebengineurlschemehandler-cannot-reply-with-a-qnetworkre suggests a different workaround: call QWebEngineUrlRequestJob::reply() in a slot connected to QNetworkReply::finished() signal. This workaround does not work for me, because the application I work on should display data as it becomes available, without waiting for it all to arrive.

      Attachments

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

        Activity

          People

            allan.jensen Allan Sandfeld Jensen
            vedg Igor Kushnir
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: