[Python-checkins] r51039 - in python/trunk: Lib/test/test_socket.py Misc/ACKS Misc/NEWS Modules/socketmodule.c
Neal Norwitz
nnorwitz at gmail.com
Wed Aug 2 08:48:37 CEST 2006
I forgot to mention that this is a backport candidate if anyone would
like to backport.
On 8/1/06, neal.norwitz <python-checkins at python.org> wrote:
> Author: neal.norwitz
> Date: Wed Aug 2 08:46:21 2006
> New Revision: 51039
>
> Modified:
> python/trunk/Lib/test/test_socket.py
> python/trunk/Misc/ACKS
> python/trunk/Misc/NEWS
> python/trunk/Modules/socketmodule.c
> Log:
> Patch #1519025 and bug #926423: If a KeyboardInterrupt occurs during
> a socket operation on a socket with a timeout, the exception will be
> caught correctly. Previously, the exception was not caught.
>
>
>
> Modified: python/trunk/Lib/test/test_socket.py
> ==============================================================================
> --- python/trunk/Lib/test/test_socket.py (original)
> +++ python/trunk/Lib/test/test_socket.py Wed Aug 2 08:46:21 2006
> @@ -11,6 +11,7 @@
> import sys
> import array
> from weakref import proxy
> +import signal
>
> PORT = 50007
> HOST = 'localhost'
> @@ -817,6 +818,37 @@
> if not ok:
> self.fail("accept() returned success when we did not expect it")
>
> + def testInterruptedTimeout(self):
> + # XXX I don't know how to do this test on MSWindows or any other
> + # plaform that doesn't support signal.alarm() or os.kill(), though
> + # the bug should have existed on all platforms.
> + if not hasattr(signal, "alarm"):
> + return # can only test on *nix
> + self.serv.settimeout(5.0) # must be longer than alarm
> + class Alarm(Exception):
> + pass
> + def alarm_handler(signal, frame):
> + raise Alarm
> + old_alarm = signal.signal(signal.SIGALRM, alarm_handler)
> + try:
> + signal.alarm(2) # POSIX allows alarm to be up to 1 second early
> + try:
> + foo = self.serv.accept()
> + except socket.timeout:
> + self.fail("caught timeout instead of Alarm")
> + except Alarm:
> + pass
> + except:
> + self.fail("caught other exception instead of Alarm")
> + else:
> + self.fail("nothing caught")
> + signal.alarm(0) # shut off alarm
> + except Alarm:
> + self.fail("got Alarm in wrong place")
> + finally:
> + # no alarm can be pending. Safe to restore old handler.
> + signal.signal(signal.SIGALRM, old_alarm)
> +
> class UDPTimeoutTest(SocketTCPTest):
>
> def testUDPTimeout(self):
>
> Modified: python/trunk/Misc/ACKS
> ==============================================================================
> --- python/trunk/Misc/ACKS (original)
> +++ python/trunk/Misc/ACKS Wed Aug 2 08:46:21 2006
> @@ -435,6 +435,7 @@
> Takahiro Nakayama
> Travers Naran
> Fredrik Nehr
> +Tony Nelson
> Chad Netzer
> Max Neunh�ffer
> George Neville-Neil
>
> Modified: python/trunk/Misc/NEWS
> ==============================================================================
> --- python/trunk/Misc/NEWS (original)
> +++ python/trunk/Misc/NEWS Wed Aug 2 08:46:21 2006
> @@ -140,6 +140,10 @@
> Extension Modules
> -----------------
>
> +- Patch #1519025 and bug #926423: If a KeyboardInterrupt occurs during
> + a socket operation on a socket with a timeout, the exception will be
> + caught correctly. Previously, the exception was not caught.
> +
> - Patch #1529514: The _ctypes extension is now compiled on more
> openbsd target platforms.
>
>
> Modified: python/trunk/Modules/socketmodule.c
> ==============================================================================
> --- python/trunk/Modules/socketmodule.c (original)
> +++ python/trunk/Modules/socketmodule.c Wed Aug 2 08:46:21 2006
> @@ -708,7 +708,7 @@
> The argument writing indicates the direction.
> This does not raise an exception; we'll let our caller do that
> after they've reacquired the interpreter lock.
> - Returns 1 on timeout, 0 otherwise. */
> + Returns 1 on timeout, -1 on error, 0 otherwise. */
> static int
> internal_select(PySocketSockObject *s, int writing)
> {
> @@ -753,6 +753,9 @@
> n = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
> }
> #endif
> +
> + if (n < 0)
> + return -1;
> if (n == 0)
> return 1;
> return 0;
> @@ -1552,7 +1555,7 @@
> &addrlen);
> Py_END_ALLOW_THREADS
>
> - if (timeout) {
> + if (timeout == 1) {
> PyErr_SetString(socket_timeout, "timed out");
> return NULL;
> }
> @@ -1923,9 +1926,15 @@
> if (s->sock_timeout > 0.0) {
> if (res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) {
> timeout = internal_select(s, 1);
> - res = connect(s->sock_fd, addr, addrlen);
> - if (res < 0 && errno == EISCONN)
> - res = 0;
> + if (timeout == 0) {
> + res = connect(s->sock_fd, addr, addrlen);
> + if (res < 0 && errno == EISCONN)
> + res = 0;
> + }
> + else if (timeout == -1)
> + res = errno; /* had error */
> + else
> + res = EWOULDBLOCK; /* timed out */
> }
> }
>
> @@ -1955,7 +1964,7 @@
> res = internal_connect(s, addr, addrlen, &timeout);
> Py_END_ALLOW_THREADS
>
> - if (timeout) {
> + if (timeout == 1) {
> PyErr_SetString(socket_timeout, "timed out");
> return NULL;
> }
> @@ -1989,6 +1998,13 @@
> res = internal_connect(s, addr, addrlen, &timeout);
> Py_END_ALLOW_THREADS
>
> + /* Signals are not errors (though they may raise exceptions). Adapted
> + from PyErr_SetFromErrnoWithFilenameObject(). */
> +#ifdef EINTR
> + if (res == EINTR && PyErr_CheckSignals())
> + return NULL;
> +#endif
> +
> return PyInt_FromLong((long) res);
> }
>
> @@ -2209,10 +2225,10 @@
> static ssize_t
> sock_recv_guts(PySocketSockObject *s, char* cbuf, int len, int flags)
> {
> - ssize_t outlen = 0;
> + ssize_t outlen = -1;
> int timeout;
> #ifdef __VMS
> - int remaining, nread;
> + int remaining;
> char *read_buf;
> #endif
>
> @@ -2228,7 +2244,7 @@
> outlen = recv(s->sock_fd, cbuf, len, flags);
> Py_END_ALLOW_THREADS
>
> - if (timeout) {
> + if (timeout == 1) {
> PyErr_SetString(socket_timeout, "timed out");
> return -1;
> }
> @@ -2243,6 +2259,7 @@
> remaining = len;
> while (remaining != 0) {
> unsigned int segment;
> + int nread = -1;
>
> segment = remaining /SEGMENT_SIZE;
> if (segment != 0) {
> @@ -2258,7 +2275,7 @@
> nread = recv(s->sock_fd, read_buf, segment, flags);
> Py_END_ALLOW_THREADS
>
> - if (timeout) {
> + if (timeout == 1) {
> PyErr_SetString(socket_timeout, "timed out");
> return -1;
> }
> @@ -2406,7 +2423,7 @@
> {
> sock_addr_t addrbuf;
> int timeout;
> - ssize_t n = 0;
> + ssize_t n = -1;
> socklen_t addrlen;
>
> *addr = NULL;
> @@ -2438,7 +2455,7 @@
> }
> Py_END_ALLOW_THREADS
>
> - if (timeout) {
> + if (timeout == 1) {
> PyErr_SetString(socket_timeout, "timed out");
> return -1;
> }
> @@ -2553,7 +2570,7 @@
> sock_send(PySocketSockObject *s, PyObject *args)
> {
> char *buf;
> - int len, n = 0, flags = 0, timeout;
> + int len, n = -1, flags = 0, timeout;
>
> if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags))
> return NULL;
> @@ -2571,7 +2588,7 @@
> #endif
> Py_END_ALLOW_THREADS
>
> - if (timeout) {
> + if (timeout == 1) {
> PyErr_SetString(socket_timeout, "timed out");
> return NULL;
> }
> @@ -2594,7 +2611,7 @@
> sock_sendall(PySocketSockObject *s, PyObject *args)
> {
> char *buf;
> - int len, n = 0, flags = 0, timeout;
> + int len, n = -1, flags = 0, timeout;
>
> if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
> return NULL;
> @@ -2605,6 +2622,7 @@
> Py_BEGIN_ALLOW_THREADS
> do {
> timeout = internal_select(s, 1);
> + n = -1;
> if (timeout)
> break;
> #ifdef __VMS
> @@ -2619,7 +2637,7 @@
> } while (len > 0);
> Py_END_ALLOW_THREADS
>
> - if (timeout) {
> + if (timeout == 1) {
> PyErr_SetString(socket_timeout, "timed out");
> return NULL;
> }
> @@ -2647,7 +2665,7 @@
> PyObject *addro;
> char *buf;
> struct sockaddr *addr;
> - int addrlen, len, n = 0, flags, timeout;
> + int addrlen, len, n = -1, flags, timeout;
>
> flags = 0;
> if (!PyArg_ParseTuple(args, "s#O:sendto", &buf, &len, &addro)) {
> @@ -2669,7 +2687,7 @@
> n = sendto(s->sock_fd, buf, len, flags, addr, addrlen);
> Py_END_ALLOW_THREADS
>
> - if (timeout) {
> + if (timeout == 1) {
> PyErr_SetString(socket_timeout, "timed out");
> return NULL;
> }
>
>
> _______________________________________________
> Python-checkins mailing list
> Python-checkins at python.org
> http://mail.python.org/mailman/listinfo/python-checkins
>
>
>
More information about the Python-checkins
mailing list