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

XMLHttpRequest.abort() does not actually abort the underlying QHttpThreadDelegate network request

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 5.11.2
    • Network: HTTP
    • None
    • macOS 10.14.2
      Qt 5.11.2 Commercial
      Creator 4.8.0
      Xcode 9.4.1
    • All

    Description

      Update: I believe this is closely related to https://bugreports.qt.io/browse/QTBUG-47966

      When you start an XMLHttpRequest, you can abort it and the underlying QQmlXMLHttpRequest and QNetworkReplyHttpImpl are properly cleaned up. However, this code:

      QNetworkReplyHttpImpl::~QNetworkReplyHttpImpl()
      {
          // This will do nothing if the request was already finished or aborted
          emit abortHttpRequest();
      }
      

      Does not actually result in the connected slot QHttpThreadDelegate::abortRequest firing. Instead, the QHttpThreadDelegate continues to run after the XMLHttpRequest has been aborted. If the QHttpThreadDelegate hangs (for instance due to a network change) this seems to cause subsequent XMLHttpRequest's to the same URL to fail to return their responses even though a network sniffer and the debugger shows they were successfully received by the app.

      — ORIGINAL TEXT BELOW —

      I have a QML application using XMLHttpRequest. This QML application needs to talk to a hardware device that presents a WiFi AP and has a well-know private address.

      The application starts off running on a WiFi network with full Internet connectivity. At a certain point, the user is instructed to switch WiFi networks to the hardware device's AP. If the QML app waits and initiates an XMLHttpRequest to the device after the WiFi network has switched, everything works fine.

      The problem is that this is not good UX. So, the app starts polling for the private address while waiting for the user to switch the WiFi networks.

      To restate, the QML app intentionally starts connecting to the private address (with a short timeout and abort) while on the wrong, Internet-connected WiFi network. The user switches to the hardware device's WiFi network. The expectation is the next HTTP request started by the QML app will succeed.

      This is where it gets weird.

      When the app initiates polling while on the wrong network, and then the user switches to the correct network, I can see with a packet sniffer (plaintext HTTP) that requests are making it from my QML app to the device, a response is sent back and the connection shuts cleanly. However, the response never makes it back up and out of XMLHttpRequest in the QML application.

      I've narrowed it down to QHttpThreadDelegate::finishedSlot and this call:

      emit downloadFinished();

      For some strange reason, under these changing network conditions, even though I step through the code and see this signal getting connected to QNetworkReplyHttpImplPrivate::replyFinished, replyFinished doesn't fire when downloadFinished is emitted. This goes on for 20 seconds or so as each request is timed out and aborted – and then it just suddenly starts working.

      I've debugged all through qqmlxmlhttprequest.cpp, qnetworkaccessmanager.cpp, qnetworkreplyhttpimpl.cpp, qhttpthreaddelegate.cpp and qhttpnetworkconnection.cpp as control hops around. I've also rebuilt Qt with -no-feature-bearermanagement and had no luck finding a root cause for this.

      I'm not sure how to make this reproducible since this hardware device is involved. Can anybody suggest where else to look or other ways to narrow down the root cause?

      Attachments

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

        Activity

          People

            cnn Qt Core & Network
            dhess David Hess
            Votes:
            2 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes