code: def read(self, n=CHUNK_SIZE):
          
          if self.closed:
              # Refuse to touch the handle after closed, it may have been reused
              # by another thread. TODO: synchronize read()/write()/close().
              return b('')
          s, disconnected = io_op(os.read, self.fd, n)
          if disconnected:
              LOG.debug('%r.read(): disconnected: %s', self, disconnected)
              return b('')
          return s
docs: Read up to `n` bytes from the file descriptor, wrapping the underlying
          :func:`os.read` call with :func:`io_op` to trap common disconnection
          conditions.
  
          :meth:`read` always behaves as if it is reading from a regular UNIX
          file; socket, pipe, and TTY disconnection errors are masked and result
          in a 0-sized read like a regular file.
  
          :returns:
              Bytes read, or the empty to string to indicate disconnection was
              detected.