[Patches] [ python-Patches-474307 ] Fix send() to send all data
noreply@sourceforge.net
noreply@sourceforge.net
Tue, 04 Dec 2001 21:27:06 -0800
Patches item #474307, was opened at 2001-10-23 18:20
You can respond by visiting:
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=474307&group_id=5470
Category: Documentation
Group: None
>Status: Closed
Resolution: Accepted
Priority: 5
Submitted By: Guido van Rossum (gvanrossum)
Assigned to: Fred L. Drake, Jr. (fdrake)
Summary: Fix send() to send all data
Initial Comment:
This patch attempts to fix the problem that
*occasionally*, *rarely*, only on *some* operating
systems, the send() call doesn't send all bytes but
returns a short count. While this is totally OK
according to the spec, it's so rare that most code
(including almost all of the standard library) assumes
that send() sends all bytes and doesn't bother to
check the return value. Such code can occasionally
misbehave, e.g. on FreeBSD which apparently returns
"short counts" more frequently than other platforms.
This has been reported before, e.g. SF bug #211710.
The fix adds a loop to the send() and sendto() calls
that repeats the call until all bytes are sent or an
error is encountered. However, the code doesn't loop
if the socket is in "non-blocking" mode, as set by the
setblocking() method. It also doesn't loop if an
explicit 'flags' argument is passed, except if flags
is -1.
Remaining problems:
- If the blocking mode of the socket is set through
other means than the setblocking() method (e.g.
through a setsockopt() call, or an fcntl() or ioctl()
call on the fileno(), or if fromfd() is passed a
non-blocking socket), the blocking flag may be wrong.
There doesn't seem to be a portable way to get the
blocking flag, and I don't want to get it before each
send() call. The caller should aways use
setblocking() to change the blocking flag.
- What should be returned if some bytes are written,
and then an error is returned by the next send() call?
I raise an exception in that case.
- This may cause blocking in a carefully constructed
application that uses blocking sockets but always
calls select() to check that a socket is writable
before calling send(). Such an application (maybe
asyncore does this?) can be fixed by passing an
explicit flags argument of zero to send().
For all these reasons, it's a tough call to decide to
apply this, and I am submitting this patch for review.
----------------------------------------------------------------------
>Comment By: Fred L. Drake, Jr. (fdrake)
Date: 2001-12-04 21:27
Message:
Logged In: YES
user_id=3066
Documentation updated with sendall() and additional
information on send() in Doc/lib/libsocket.tex revision 1.58.
----------------------------------------------------------------------
Comment By: Guido van Rossum (gvanrossum)
Date: 2001-10-25 20:25
Message:
Logged In: YES
user_id=6380
I've checked in sendall().
I'm handing this over to Fred for documentation.
----------------------------------------------------------------------
Comment By: Guido van Rossum (gvanrossum)
Date: 2001-10-25 06:07
Message:
Logged In: YES
user_id=6380
Here's a patch that implements sendall().
----------------------------------------------------------------------
Comment By: Guido van Rossum (gvanrossum)
Date: 2001-10-25 06:06
Message:
Logged In: YES
user_id=6380
Here's a patch that implements sendall().
----------------------------------------------------------------------
Comment By: Guido van Rossum (gvanrossum)
Date: 2001-10-25 05:50
Message:
Logged In: YES
user_id=6380
That's a possibility. I'd prefer a sendall() method in that
case.
I'm not sure I have the time for that; can you give it a
crack? It would be much simpler than my patch.
----------------------------------------------------------------------
Comment By: Anthony Baxter (anthonybaxter)
Date: 2001-10-24 23:23
Message:
Logged In: YES
user_id=29957
How about, as a position in between, a new flag to send()
to say 'send all of it'. That way, we can choose what
semantics it should have. This simplifies the process of
patching the std library for 2.2.
Hm. socket.send() should probably be documented more
clearly that it doesn't necessarily send all bytes.
----------------------------------------------------------------------
Comment By: Guido van Rossum (gvanrossum)
Date: 2001-10-24 12:10
Message:
Logged In: YES
user_id=6380
We discussed this at a PythonLabs meeting and rejected it,
because it's impossible to really do the right thing at this
level. Instead, we're going to have to fix all calls to send
that don't check the return value.
- Having the wrong value for the 'blocking' bit is not safe,
and there's no portable way to get the blocking bit.
- There's no good answer to the question of what to do when
the looping call encounters an error after some bytes were
written successfully. On the one hand we want to report the
error, on the other hand we want to report how many bytes
were written. Making this part of the exception state is too
messy.
- There's much more documentation for socket programming in
C than in Python, and it's a real advantage to be able to do
a 1-1 translation between C examples to Python examples.
----------------------------------------------------------------------
You can respond by visiting:
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=474307&group_id=5470