[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