This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author akira
Recipients akira, asvetlov, christian.heimes, giampaolo.rodola, gvanrossum, josh.r, josiah.carlson, neologix, pitrou, rosslagerwall, yselivanov
Date 2014-04-24.11:05:12
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
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(
        interval = self.timeout
        if interval is not None:
             deadline = now() + interval
        while select([], [self], [], interval)[1]: # writable
                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:
                continue # ignore
                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:
        # timeout
        if total == 0:
            raise TimeoutError
            return total
Date User Action Args
2014-04-24 11:05:12akirasetrecipients: + akira, gvanrossum, pitrou, giampaolo.rodola, christian.heimes, josiah.carlson, asvetlov, neologix, rosslagerwall, yselivanov, josh.r
2014-04-24 11:05:12akirasetmessageid: <>
2014-04-24 11:05:12akiralinkissue17552 messages
2014-04-24 11:05:12akiracreate