Skip to content

URL Handler Protocol Socket in_waiting Implementation Is Incorrect #759

Open
@cbreins

Description

@cbreins

The current implementation is shown below from url_handler.protocol_socket.Serial. The select call returns whether or not data is ready as shown by the ready loop in the read function and not the number of bytes in waiting. This is particularly a problem when using the ReaderThread class as it causes the run loop to "busy" loop and consume excessive amounts of CPU.

@property
def in_waiting(self):
    """Return the number of bytes currently in the input buffer."""
    if not self.is_open:
        raise PortNotOpenError()
    # Poll the socket to see if it is ready for reading.
    # If ready, at least one byte will be to read.
    lr, lw, lx = select.select([self._socket], [], [], 0)
    return len(lr)

while len(read) < size:
    try:
        ready, _, _ = select.select([self._socket], [], [], timeout.time_left())

I have included a possible fix below. I have tested the implementation on Unix (Linux Ubuntu 20.04), but I don't have access to a Windows machine at the moment to verify the windows implementation.

  @property
  def in_waiting(self):
    """Return the number of bytes currently in the input buffer."""
    if not self.is_open:
        raise PortNotOpenError()
        
    if os.name == 'nt':  # Windows
        return len(sock.recv(4096, socket.MSG_PEEK))
        
    else:  # POSIX (Unix-like)
        import fcntl
        import struct
        import termios
        
        buf = fcntl.ioctl(self._socket, termios.FIONREAD, struct.pack("I", 0))
        nbytes = struct.unpack("I", buf)[0]
        return nbytes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions