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 neologix
Recipients exarkun, mdcowles, neologix, pitrou
Date 2010-04-26.12:48:01
SpamBayes Score 3.330669e-16
Marked as misclassified No
Message-id <1272286083.97.0.565883285977.issue8493@psf.upfronthosting.co.za>
In-reply-to
Content
> What is the mnemonic corresponding to errno 35 under OS X?
(under Linux I get EDEADLOCK, which probably isn't the right one)

From the first message: "errno 35 (resource temporarily unavailable)". It's actually EAGAIN on Linux (which makes sense on a non-blocking socket).

> By the way, rather than sleeping a fixed amount of time before retrying, you could probably use select() on the socket.

select doesn't mean much for sockets you want to send to, because it will report the socket in the writable set as soon as there's one byte free in the send buffer, so you can very well block (or fail in that case) even when select reports the socket as ready for writting.

> If you set a timeout on a socket, it is really non-blocking internally (from the OS' point of view). So perhaps this is what you are witnessing.

Yes. Maybe it would help to have the sample code ?

Googling a little bit gave this: http://lists.freebsd.org/pipermail/freebsd-hackers/2004-January/005369.html

> > I have written a test program,
> > http://www.infres.enst.fr/~pook/send/server.c, that shows that send does
> > not block on FreeBSD.  It does with Linux and Solaris.
> 
> Do you know what the behaviour of Net- and/or OpenBSD is?

NetBSD is the same as FreeBSD.  I have not tested OpenBSD.
MacOS X is similiar to FreeBSD in that send doesn't block, howver
the send does not give an error: the packet is just thrown away.

So there seems to be an issue on some systems when you run out of socket buffers, and since select doesn't seem to work either, I guess the only option is this sleep-a-little-hoping-the-buffer-gets-drained approach.

> I think this is a bug in Python's socket module.
> recv()-like functions are written so as to first call select() before actually receiving data, but send()-like functions aren't. I guess blocking sends are quite rare thanks to in-kernel buffering, but we should do the correct thing and use the same logic for send() as we do for recv().

When I look at trunk, I see this:

do {
		timeout = internal_select(s, 1);
		n = -1;
		if (timeout)
			break;
#ifdef __VMS
		n = sendsegmented(s->sock_fd, buf, len, flags);
#else
		n = send(s->sock_fd, buf, len, flags);
#endif
		if (n < 0) {
#ifdef EINTR
			/* We must handle EINTR here as there is no way for
			 * the caller to know how much was sent otherwise.  */
			if (errno == EINTR) {
				/* Run signal handlers.  If an exception was
				 * raised, abort and leave this socket in
				 * an unknown state. */
				if (PyErr_CheckSignals())
					return NULL;
				continue;
			}
#endif
			break;
		}
		buf += n;
		len -= n;
	} while (len > 0);

we call internal_select(s, 1) (1 for writting) before sending.
But as I said, it's not reliable.
History
Date User Action Args
2010-04-26 12:48:04neologixsetrecipients: + neologix, mdcowles, exarkun, pitrou
2010-04-26 12:48:03neologixsetmessageid: <1272286083.97.0.565883285977.issue8493@psf.upfronthosting.co.za>
2010-04-26 12:48:02neologixlinkissue8493 messages
2010-04-26 12:48:01neologixcreate