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

windows - QAbstractSocket::waitForXXX functions are unreliable

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 4.8.0, 5.0.0
    • Network: Sockets

    Description

      When select() is called in the native socket engine:
      if data was already available in the socket, it completes immediately with success (OK)
      if data is received from the network while the select call is active, it times out (ERROR)

      In the error case, immediately calling nativeBytesAvailable() after the select() times out shows the data is there in the socket.

      The result of this is that the WaitForXXX functions only work correctly with a timeout of zero.
      This causes network autotests to fail randomly (mainly the low level tests e.g. qtcpsocket) with timeouts on waitForReadyRead / waitForConnected.
      Enabling any debug traces will hide the problem. (triggers the "data already available in the socket" case)

      This might be due to mixing of programming models.
      The windows event dispatcher is using WSAAsyncSelect (which notifies completion via window messages)

      Cancelling both the read and write socket notifiers results in WSAAsyncSelect being called with events = 0, which should detach the socket from the async event handler, however this does not have any effect on the bad behaviour we can see in select().
      WSAPoll() has the same problem as select()

      Calling WSAEventSelect() inside nativeSelect() results in spin, because the call resets the socket flags - therefore write notifier is constantly signalled. The proper way to use this API is to call it once at socket initialisation, and then wait on the event object where you'd normally call select()

      It is documented that WSAAsyncSelect and WSAEventSelect cannot be used together. (calling one cancels the other)
      The documentation says nothing about WSAAsyncSelect and select though.

      A possible solution is to use WSAEventSelect everywhere, and use the event handle in the MsgWaitForMultipleObjectsEx call in the event dispatcher, or wait on a specific event object in nativeSelect.
      This means sharing the event object between the event dispatcher and the socket (it is not allowed to have more than one event object attached to the same socket handle)

      QSocketNotifier being a public API is the most difficult thing about this approach.
      Also the fact that WSAEVENT is compatible with WaitForMultipleObjectsEx may be an implementation detail.
      We can't use WSAWaitForMultipleEvents in the event dispatcher because other types of event and window messages won't complete it.

      Attachments

        Issue Links

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

          Activity

            People

              cnn Qt Core & Network
              shkearns Shane Kearns
              Votes:
              20 Vote for this issue
              Watchers:
              29 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes