[Python-Dev] [Python-checkins] cpython (2.7): Issue #9090 : Error code 10035 calling socket.recv() on a socket with a timeout (original) (raw)
Kristján Valur Jónsson kristjan at ccpgames.com
Tue Mar 19 20:49:16 CET 2013
- Previous message: [Python-Dev] [Python-checkins] cpython (2.7): Issue #9090 : Error code 10035 calling socket.recv() on a socket with a timeout
- Next message: [Python-Dev] [Python-checkins] cpython (2.7): Issue #9090 : Error code 10035 calling socket.recv() on a socket with a timeout
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Apparently timemodule is not a built-in module on linux. But it is on windows. Funny!
-----Original Message----- From: Python-Dev [mailto:python-dev-bounces+kristjan=ccpgames.com at python.org] On Behalf Of Kristján Valur Jónsson Sent: 19. mars 2013 12:34 To: python-dev at python.org Subject: Re: [Python-Dev] [Python-checkins] cpython (2.7): Issue #9090 : Error code 10035 calling socket.recv() on a socket with a timeout
Yes, it is a symbol problem on unix. Working on it.
-----Original Message----- From: Python-checkins [mailto:python-checkins-bounces+kristjan=ccpgames.com at python.org] On Behalf Of Senthil Kumaran Sent: 19. mars 2013 12:28 To: sweskman at gmail.com Cc: python-checkins at python.org Subject: Re: [Python-checkins] cpython (2.7): Issue #9090 : Error code 10035 calling socket.recv() on a socket with a timeout
Looks like RHEL 2.7 buildbots are unhappy with this change.
-- Senthil
On Tue, Mar 19, 2013 at 11:08 AM, kristjan.jonsson <python-checkins at python.org> wrote:
http://hg.python.org/cpython/rev/8ec39bfd1f01 changeset: 82764:8ec39bfd1f01 branch: 2.7 parent: 82740:b10ec5083a53 user: Kristján Valur Jónsson <sweskman at gmail.com> date: Tue Mar 19 10:58:59 2013 -0700 summary: Issue #9090 : Error code 10035 calling socket.recv() on a socket with a timeout (WSAEWOULDBLOCK - A non-blocking socket operation could not be completed immediately)
files: Misc/NEWS | 5 + Modules/socketmodule.c | 104 ++++++++++++++++++++++++---- Modules/timemodule.c | 7 + 3 files changed, 101 insertions(+), 15 deletions(-)
diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -214,6 +214,11 @@ Library ------- +- Issue #9090: When a socket with a timeout fails with EWOULDBLOCK or +EAGAIN, + retry the select() loop instead of bailing out. This is because +select() + can incorrectly report a socket as ready for reading (for example, +if it + received some data with an invalid checksum). + - Issue #1285086: Get rid of the refcounting hack and speed up urllib.unquote(). - Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -473,6 +473,17 @@ return NULL; } +#ifdef MSWINDOWS +#ifndef WSAEAGAIN +#define WSAEAGAIN WSAEWOULDBLOCK +#endif _+#define CHECKERRNO(expected) _ + (WSAGetLastError() == WSA ## expected) #else #define _+CHECKERRNO(expected) _ + (errno == expected) +#endif + /* Convenience function to raise an error according to errno and return a NULL pointer from a function. */ @@ -661,7 +672,7 @@ after they've reacquired the interpreter lock. Returns 1 on timeout, -1 on error, 0 otherwise. */ static int -internalselect(PySocketSockObject *s, int writing) +internalselectex(PySocketSockObject *s, int writing, double +interval) { int n; @@ -673,6 +684,10 @@ if (s->sockfd < 0)_ _return 0;_ _+ /* Handling this condition here simplifies the select loops */_ _+ if (interval < 0.0)_ _+ return 1;_ _+_ _/* Prefer poll, if available, since you can poll() any fd_ _* which can't be done with select(). */ #ifdef HAVEPOLL @@_ _-684,7 +699,7 @@_ _pollfd.events = writing ? POLLOUT : POLLIN;_ _/* s->socktimeout is in seconds, timeout in ms */ - timeout = (int)(s->socktimeout * 1000 + 0.5); + timeout = (int)(interval * 1000 + 0.5); n = poll(&pollfd, 1, timeout); } #else @@ -692,8 +707,8 @@ /* Construct the arguments to select */ fdset fds; struct timeval tv; - tv.tvsec = (int)s->socktimeout; - tv.tvusec = (int)((s->socktimeout - tv.tvsec) * 1e6); + tv.tvsec = (int)interval; + tv.tvusec = (int)((interval - tv.tvsec) * 1e6); FDZERO(&fds); FDSET(s->sockfd, &fds); @@ -712,6 +727,49 @@ return 0; } +static int +internalselect(PySocketSockObject *s, int writing) { + return internalselectex(s, writing, s->socktimeout); } + +/* + Two macros for automatic retry of select() in case of false positives + (for example, select() could indicate a socket is ready for reading + but the data then discarded by the OS because of a wrong checksum). + Here is an example of use: + + BEGINSELECTLOOP(s) + PyBEGINALLOWTHREADS + timeout = internalselectex(s, 0, interval); + if (!timeout) + outlen = recv(s->sockfd, cbuf, len, flags); + PyENDALLOWTHREADS + if (timeout == 1) { + PyErrSetString(sockettimeout, "timed out"); + return -1; + } + ENDSELECTLOOP(s) +*/ +PyAPIFUNC(double) PyTimefloattime(void); /* defined in _+timemodule.c / #define BEGINSELECTLOOP(s) _ _+ { _ _+ double deadline, interval = s->socktimeout; _ _+ int hastimeout = s->socktimeout > 0.0; _ _+ if (hastimeout) { _ _+ deadline = PyTimefloattime() + s->socktimeout; _ _+ } _ _+ while (1) { _ _+ errno = 0; _ + _+#define ENDSELECTLOOP(s) _ _+ if (!hastimeout || _ _+ (!CHECKERRNO(EWOULDBLOCK) && !CHECKERRNO(EAGAIN))) _ _+ break; _ _+ interval = deadline - PyTimefloattime(); _ _+ } _ _+ } _ + _/ Initialize a new socket object. /_ _static double defaulttimeout = -1.0; / Default timeout for new_ sockets */ @@ -1656,8 +1714,9 @@ if (!ISSELECTABLE(s)) return selecterror(); + BEGINSELECTLOOP(s) PyBEGINALLOWTHREADS - timeout = internalselect(s, 0); + timeout = internalselectex(s, 0, interval); if (!timeout) newfd = accept(s->sockfd, SAS2SA(&addrbuf), &addrlen); PyENDALLOWTHREADS @@ -1666,6 +1725,7 @@ PyErrSetString(sockettimeout, "timed out"); return NULL; } + ENDSELECTLOOP(s) #ifdef MSWINDOWS if (newfd == INVALIDSOCKET) @@ -2355,8 +2415,9 @@ } _#ifndef VMS + BEGINSELECTLOOP(s) PyBEGINALLOWTHREADS - timeout = internalselect(s, 0); + timeout = internalselectex(s, 0, interval); if (!timeout) outlen = recv(s->sockfd, cbuf, len, flags); PyENDALLOWTHREADS @@ -2365,6 +2426,7 @@ PyErrSetString(sockettimeout, "timed out"); return -1; } + ENDSELECTLOOP(s) if (outlen < 0) {_ _/* Note: the call to errorhandler() ALWAYS indirectly returned_ _NULL, so ignore its return value */ @@ -2386,8 +2448,9 @@_ _segment = remaining;_ _}_ _+ BEGINSELECTLOOP(s)_ _PyBEGINALLOWTHREADS_ _- timeout = internalselect(s, 0);_ _+ timeout = internalselectex(s, 0, interval);_ _if (!timeout)_ _nread = recv(s->sockfd, readbuf, segment, flags); PyENDALLOWTHREADS @@ -2396,6 +2459,8 @@ PyErrSetString(sockettimeout, "timed out"); return -1; } + ENDSELECTLOOP(s) + if (nread < 0) {_ _s->errorhandler(); return -1; @@ -2559,9 +2624,10 @@ return -1; } + BEGINSELECTLOOP(s) PyBEGINALLOWTHREADS memset(&addrbuf, 0, addrlen); - timeout = internalselect(s, 0); + timeout = internalselectex(s, 0, interval); if (!timeout) { #ifndef MSWINDOWS #if defined(PYOSOS2) && !defined(PYCCGCC) @@ -2582,6 +2648,7 @@ PyErrSetString(sockettimeout, "timed out"); return -1; } + ENDSELECTLOOP(s) if (n < 0) {_ _s->errorhandler(); return -1; @@ -2719,8 +2786,9 @@ buf = pbuf.buf; len = pbuf.len; + BEGINSELECTLOOP(s) PyBEGINALLOWTHREADS - timeout = internalselect(s, 1); + timeout = internalselectex(s, 1, interval); if (!timeout) _#ifdef VMS n = sendsegmented(s->sockfd, buf, len, flags); @@ -2728,13 +2796,14 @@ n = send(s->sockfd, buf, len, flags); #endif PyENDALLOWTHREADS - - PyBufferRelease(&pbuf); - if (timeout == 1) { + PyBufferRelease(&pbuf); PyErrSetString(sockettimeout, "timed out"); return NULL; } + ENDSELECTLOOP(s) + + PyBufferRelease(&pbuf); if (n < 0)_ _return s->errorhandler(); return PyIntFromLong((long)n); @@ -2768,8 +2837,9 @@ } do { + BEGINSELECTLOOP(s) PyBEGINALLOWTHREADS - timeout = internalselect(s, 1); + timeout = internalselectex(s, 1, interval); n = -1; if (!timeout) { _#ifdef VMS @@ -2784,6 +2854,7 @@ PyErrSetString(sockettimeout, "timed out"); return NULL; } + ENDSELECTLOOP(s) /* PyErrCheckSignals() might change errno */ savederrno = errno; /* We must run our signal handlers before looping again. @@ -2863,17 +2934,20 @@ return NULL; } + BEGINSELECTLOOP(s) PyBEGINALLOWTHREADS - timeout = internalselect(s, 1); + timeout = internalselectex(s, 1, interval); if (!timeout) n = sendto(s->sockfd, buf, len, flags, SAS2SA(&addrbuf), addrlen); PyENDALLOWTHREADS - PyBufferRelease(&pbuf); if (timeout == 1) { + PyBufferRelease(&pbuf); PyErrSetString(sockettimeout, "timed out"); return NULL; } + ENDSELECTLOOP(s) + PyBufferRelease(&pbuf); if (n < 0)_ _return s->errorhandler(); return PyIntFromLong((long)n); diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1055,3 +1055,10 @@ return 0; } + +/* export floattime to socketmodule.c */ +PyAPIFUNC(double) +PyTimefloattime(void) +{ + return floattime(); +} -- Repository URL: http://hg.python.org/cpython
Python-checkins mailing list Python-checkins at python.org http://mail.python.org/mailman/listinfo/python-checkins
Python-checkins mailing list Python-checkins at python.org http://mail.python.org/mailman/listinfo/python-checkins
Python-Dev mailing list Python-Dev at python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/kristjan%40ccpgames.com
- Previous message: [Python-Dev] [Python-checkins] cpython (2.7): Issue #9090 : Error code 10035 calling socket.recv() on a socket with a timeout
- Next message: [Python-Dev] [Python-checkins] cpython (2.7): Issue #9090 : Error code 10035 calling socket.recv() on a socket with a timeout
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]