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

QLocalSocket messes up the message queue

    XMLWordPrintable

Details

    • Bug
    • Resolution: Incomplete
    • P4: Low
    • None
    • 5.9.4
    • Network: Sockets
    • None
    • openSUSE Leap 15.0
    • Linux/X11

    Description

      Consider two processes, A and B, and A sends data to B through QLocalSocket. Both processes are single-threaded and do all their work inside QCoreApplication::exec().

      A common approach is for process B to have a slot connected to the readyRead signal of the QLocalSocket. Since there is only one thread, the default Qt::AutoConnection connection type will translate to Qt::DirectConnection.

      Suppose that the data processing inside this slot takes longer than it takes for process A to send a new portion of data. In this case, upon completion of this slot, it will be immediately called again, and then again, ad infinitum. The event loop will never process any messages.

      I didn’t delve into the Qt source code, but something tells me that every iteration of the event loop starts with something like poll(2) on socket descriptors, followed by reading from them in case there is new data, followed by emitting the readyRead signal.

      This can be somewhat alleviated by explicitly specifying Qt::QueuedConnection when connecting to readyRead slot, but I think such drastic impact on the application behavior should probably be mentioned in the QLocalSocket documentation.

      Since we are talking about QLocalSocket, another thing that should probably be mentioned is the semantics of the state change. In case the Rx buffer of process B goes above the readBufferSize limit, QLocalSocket stops updating its state. Moreover, it won’t update its state even after the process reads data from its Rx buffer, as long as there is more data in the socket – even if the socket has disconnected long ago.
      In other words, if you (for example)

      • set readBufferSize limit
      • don’t read data from the socket
      • wait for disconnected signal,

      then there is a chance that you will never get it, even after the other process has already finished.
      Once again, I have no problems with the semantics itself (although I would’ve definitely emitted the disconnected signal as soon as the socket is, well, disconnected – after all, it’s perfectly fine to read data from a disconnected QLocalSocket, as long as it is opened in the QIODevice sense). But I strongly believe that this behavior should be mentioned in the documentation.

      Finally, there is a downright misleading figure of speech in the QLocalSocket::readBufferSize() documentation:
      «A read buffer size of 0 (the default) means that the buffer has no size limit, ensuring that no data is lost».
      This suggests that limiting readBufferSize might lead to data loss, which does not seem to be correct. If readBufferSize is limited and process A generates data faster than process B reads it, the data will first fill the socket buffer (owned by the OS), and then start piling up in the Tx buffer of the QLocalSocket inside process A. Nothing will be lost (unless process A calls abort() while its QLocalSocket still has unsent data in its Tx buffer, but this is a no-brainer).

      Attachments

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

        Activity

          People

            tpochep Timur Pocheptsov
            scumcoder Daniil Larionov
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes