[issue17552] socket.sendfile()

akira report at bugs.python.org
Thu Apr 24 13:05:12 CEST 2014


akira added the comment:

use_fallback parameter is mostly a debugging tool.  If it helps to avoid the
indecision; I would side with neologix' remarks and also suggest to drop
the use_fallback parameter.

It seems the patch assumes *offset == nbytes_sent* that is false in general
e.g., if offset > 0 at the start of the function.

::

    _SEND_BLOCKSIZE = 262144 # ???

    def sendfile(self, file, offset=None, nbytes=None,
             *, nbytes_per_send=_SEND_BLOCKSIZE) -> nbytes_sent:
        """
        Send *nbytes* bytes from regular *file* starting at *offset* position.

        Return the number of bytes sent.

        If *offset* is ``None``; start at the current file position.
        If *nbytes* is ``None``; send file until EOF is reached.

        The socket should be connection-oriented e.g., SOCK_STREAM

        *nbytes_per_send* is used by a *send()*-based fallback code.
        *os.sendfile()* ignores it.

        - if socket is blocking (timeout is None) then it may keep
          trying to send data until an error occurs.

          Even on success it may return less than *nbytes* if there is
          not enough data available in *file*.

        - if socket is non-blocking and timeout == 0 then fail if
          even a single byte can't be sent immediately

        - if socket has timeout > 0 then raise the timeout error if
          more than *timeout* seconds pass since the call is started
          and nothing is sent i.e., use a single deadline for all
          system calls (like *socket.send()*).

        If timeout is not None then *socket.sendfile()* may send less
        bytes than specified.

        *file* position after the call is unspecified.

        """
        # pseudo-code
        total = 0
        if offset is None
            offset = file.tell()
        if nbytes is None:
            nbytes = os.path.getsize(file.name)
        interval = self.timeout
        if interval is not None:
             deadline = now() + interval
        while select([], [self], [], interval)[1]: # writable
            try:
                sent = os.sendfile(self, file, offset, nbytes)
            except BlockingIOError as e:
                assert getattr(e, 'characters_written', 0) == 0
                if interval is not None: # update interval
                    interval = deadline - now()
                    if interval < 0:
                        break
                continue # ignore
            else:
                if sent == 0:
                    return total
            total += sent
            offset += sent
            nbytes -= sent
            if nbytes == 0:
                return total
            if interval is not None: # update interval
                interval = deadline - now()
                if interval < 0:
                    break
        # timeout
        if total == 0:
            raise TimeoutError
        else:
            return total

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue17552>
_______________________________________


More information about the Python-bugs-list mailing list