Yes, it is a symbol problem on unix. Working on it. -----Original Message----- From: Python-checkins [mailto:python-checkins-bounces+kristjan=ccpgames....@python.org] On Behalf Of Senthil Kumaran Sent: 19. mars 2013 12:28 To: swesk...@gmail.com Cc: python-check...@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-check...@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 <swesk...@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 MS_WINDOWS > +#ifndef WSAEAGAIN > +#define WSAEAGAIN WSAEWOULDBLOCK > +#endif > +#define CHECK_ERRNO(expected) \ > + (WSAGetLastError() == WSA ## expected) #else #define > +CHECK_ERRNO(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 > -internal_select(PySocketSockObject *s, int writing) > +internal_select_ex(PySocketSockObject *s, int writing, double > +interval) > { > int n; > > @@ -673,6 +684,10 @@ > if (s->sock_fd < 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 HAVE_POLL @@ > -684,7 +699,7 @@ > pollfd.events = writing ? POLLOUT : POLLIN; > > /* s->sock_timeout is in seconds, timeout in ms */ > - timeout = (int)(s->sock_timeout * 1000 + 0.5); > + timeout = (int)(interval * 1000 + 0.5); > n = poll(&pollfd, 1, timeout); > } > #else > @@ -692,8 +707,8 @@ > /* Construct the arguments to select */ > fd_set fds; > struct timeval tv; > - tv.tv_sec = (int)s->sock_timeout; > - tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6); > + tv.tv_sec = (int)interval; > + tv.tv_usec = (int)((interval - tv.tv_sec) * 1e6); > FD_ZERO(&fds); > FD_SET(s->sock_fd, &fds); > > @@ -712,6 +727,49 @@ > return 0; > } > > +static int > +internal_select(PySocketSockObject *s, int writing) { > + return internal_select_ex(s, writing, s->sock_timeout); } > + > +/* > + 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: > + > + BEGIN_SELECT_LOOP(s) > + Py_BEGIN_ALLOW_THREADS > + timeout = internal_select_ex(s, 0, interval); > + if (!timeout) > + outlen = recv(s->sock_fd, cbuf, len, flags); > + Py_END_ALLOW_THREADS > + if (timeout == 1) { > + PyErr_SetString(socket_timeout, "timed out"); > + return -1; > + } > + END_SELECT_LOOP(s) > +*/ > +PyAPI_FUNC(double) _PyTime_floattime(void); /* defined in timemodule.c */ > +#define BEGIN_SELECT_LOOP(s) \ > + { \ > + double deadline, interval = s->sock_timeout; \ > + int has_timeout = s->sock_timeout > 0.0; \ > + if (has_timeout) { \ > + deadline = _PyTime_floattime() + s->sock_timeout; \ > + } \ > + while (1) { \ > + errno = 0; \ > + > +#define END_SELECT_LOOP(s) \ > + if (!has_timeout || \ > + (!CHECK_ERRNO(EWOULDBLOCK) && !CHECK_ERRNO(EAGAIN))) \ > + break; \ > + interval = deadline - _PyTime_floattime(); \ > + } \ > + } \ > + > /* Initialize a new socket object. */ > > static double defaulttimeout = -1.0; /* Default timeout for new sockets */ > @@ -1656,8 +1714,9 @@ > if (!IS_SELECTABLE(s)) > return select_error(); > > + BEGIN_SELECT_LOOP(s) > Py_BEGIN_ALLOW_THREADS > - timeout = internal_select(s, 0); > + timeout = internal_select_ex(s, 0, interval); > if (!timeout) > newfd = accept(s->sock_fd, SAS2SA(&addrbuf), &addrlen); > Py_END_ALLOW_THREADS > @@ -1666,6 +1725,7 @@ > PyErr_SetString(socket_timeout, "timed out"); > return NULL; > } > + END_SELECT_LOOP(s) > > #ifdef MS_WINDOWS > if (newfd == INVALID_SOCKET) > @@ -2355,8 +2415,9 @@ > } > > #ifndef __VMS > + BEGIN_SELECT_LOOP(s) > Py_BEGIN_ALLOW_THREADS > - timeout = internal_select(s, 0); > + timeout = internal_select_ex(s, 0, interval); > if (!timeout) > outlen = recv(s->sock_fd, cbuf, len, flags); > Py_END_ALLOW_THREADS > @@ -2365,6 +2426,7 @@ > PyErr_SetString(socket_timeout, "timed out"); > return -1; > } > + END_SELECT_LOOP(s) > if (outlen < 0) { > /* Note: the call to errorhandler() ALWAYS indirectly returned > NULL, so ignore its return value */ > @@ -2386,8 +2448,9 @@ > segment = remaining; > } > > + BEGIN_SELECT_LOOP(s) > Py_BEGIN_ALLOW_THREADS > - timeout = internal_select(s, 0); > + timeout = internal_select_ex(s, 0, interval); > if (!timeout) > nread = recv(s->sock_fd, read_buf, segment, flags); > Py_END_ALLOW_THREADS > @@ -2396,6 +2459,8 @@ > PyErr_SetString(socket_timeout, "timed out"); > return -1; > } > + END_SELECT_LOOP(s) > + > if (nread < 0) { > s->errorhandler(); > return -1; > @@ -2559,9 +2624,10 @@ > return -1; > } > > + BEGIN_SELECT_LOOP(s) > Py_BEGIN_ALLOW_THREADS > memset(&addrbuf, 0, addrlen); > - timeout = internal_select(s, 0); > + timeout = internal_select_ex(s, 0, interval); > if (!timeout) { > #ifndef MS_WINDOWS > #if defined(PYOS_OS2) && !defined(PYCC_GCC) > @@ -2582,6 +2648,7 @@ > PyErr_SetString(socket_timeout, "timed out"); > return -1; > } > + END_SELECT_LOOP(s) > if (n < 0) { > s->errorhandler(); > return -1; > @@ -2719,8 +2786,9 @@ > buf = pbuf.buf; > len = pbuf.len; > > + BEGIN_SELECT_LOOP(s) > Py_BEGIN_ALLOW_THREADS > - timeout = internal_select(s, 1); > + timeout = internal_select_ex(s, 1, interval); > if (!timeout) > #ifdef __VMS > n = sendsegmented(s->sock_fd, buf, len, flags); > @@ -2728,13 +2796,14 @@ > n = send(s->sock_fd, buf, len, flags); > #endif > Py_END_ALLOW_THREADS > - > - PyBuffer_Release(&pbuf); > - > if (timeout == 1) { > + PyBuffer_Release(&pbuf); > PyErr_SetString(socket_timeout, "timed out"); > return NULL; > } > + END_SELECT_LOOP(s) > + > + PyBuffer_Release(&pbuf); > if (n < 0) > return s->errorhandler(); > return PyInt_FromLong((long)n); > @@ -2768,8 +2837,9 @@ > } > > do { > + BEGIN_SELECT_LOOP(s) > Py_BEGIN_ALLOW_THREADS > - timeout = internal_select(s, 1); > + timeout = internal_select_ex(s, 1, interval); > n = -1; > if (!timeout) { > #ifdef __VMS > @@ -2784,6 +2854,7 @@ > PyErr_SetString(socket_timeout, "timed out"); > return NULL; > } > + END_SELECT_LOOP(s) > /* PyErr_CheckSignals() might change errno */ > saved_errno = errno; > /* We must run our signal handlers before looping again. > @@ -2863,17 +2934,20 @@ > return NULL; > } > > + BEGIN_SELECT_LOOP(s) > Py_BEGIN_ALLOW_THREADS > - timeout = internal_select(s, 1); > + timeout = internal_select_ex(s, 1, interval); > if (!timeout) > n = sendto(s->sock_fd, buf, len, flags, SAS2SA(&addrbuf), addrlen); > Py_END_ALLOW_THREADS > > - PyBuffer_Release(&pbuf); > if (timeout == 1) { > + PyBuffer_Release(&pbuf); > PyErr_SetString(socket_timeout, "timed out"); > return NULL; > } > + END_SELECT_LOOP(s) > + PyBuffer_Release(&pbuf); > if (n < 0) > return s->errorhandler(); > return PyInt_FromLong((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 */ > +PyAPI_FUNC(double) > +_PyTime_floattime(void) > +{ > + return floattime(); > +} > > -- > Repository URL: http://hg.python.org/cpython > > _______________________________________________ > Python-checkins mailing list > python-check...@python.org > http://mail.python.org/mailman/listinfo/python-checkins > _______________________________________________ Python-checkins mailing list python-check...@python.org http://mail.python.org/mailman/listinfo/python-checkins _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com