]> granicus.if.org Git - python/commitdiff
Issue #28471: Fix crash (GIL state related) in socket.setblocking
authorYury Selivanov <yury@magic.io>
Tue, 18 Oct 2016 20:03:52 +0000 (16:03 -0400)
committerYury Selivanov <yury@magic.io>
Tue, 18 Oct 2016 20:03:52 +0000 (16:03 -0400)
Lib/test/test_socket.py
Misc/NEWS
Modules/socketmodule.c

index c9add6cc98cb1b72bf8144876a2e1e84f80520a2..0cf7bfe29391acfbe0f51f8ef52d8d2be6b1c3ff 100644 (file)
@@ -4552,6 +4552,18 @@ class TestExceptions(unittest.TestCase):
         self.assertTrue(issubclass(socket.gaierror, OSError))
         self.assertTrue(issubclass(socket.timeout, OSError))
 
+    def test_setblocking_invalidfd(self):
+        # Regression test for issue #28471
+
+        sock0 = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+        sock = socket.socket(
+            socket.AF_INET, socket.SOCK_STREAM, 0, sock0.fileno())
+        sock0.close()
+
+        with self.assertRaises(OSError):
+            sock.setblocking(False)
+
+
 @unittest.skipUnless(sys.platform == 'linux', 'Linux specific test')
 class TestLinuxAbstractNamespace(unittest.TestCase):
 
index 5d972fdea804ea73f5bcede44eb2d60b6ba2030d..f3a3d55b63457a4cad02a6ef9fbfdf2696498b2f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,10 @@ Core and Builtins
 - Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
   loss in PyTraceBack_Here().
 
+- Issue #28471: Fix "Python memory allocator called without holding the GIL"
+  crash in socket.setblocking.
+
+
 Library
 -------
 
index d25bd7f7980fd2f028d86a8de46f1162a141dabe..f53eadeb6c00c77ff29328de33897be1e486c065 100644 (file)
@@ -622,6 +622,7 @@ set_gaierror(int error)
 static int
 internal_setblocking(PySocketSockObject *s, int block)
 {
+    int result = -1;
 #ifdef MS_WINDOWS
     u_long arg;
 #endif
@@ -641,34 +642,39 @@ internal_setblocking(PySocketSockObject *s, int block)
 #if (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO))
     block = !block;
     if (ioctl(s->sock_fd, FIONBIO, (unsigned int *)&block) == -1)
-        goto error;
+        goto done;
 #else
     delay_flag = fcntl(s->sock_fd, F_GETFL, 0);
     if (delay_flag == -1)
-        goto error;
+        goto done;
     if (block)
         new_delay_flag = delay_flag & (~O_NONBLOCK);
     else
         new_delay_flag = delay_flag | O_NONBLOCK;
     if (new_delay_flag != delay_flag)
         if (fcntl(s->sock_fd, F_SETFL, new_delay_flag) == -1)
-            goto error;
+            goto done;
 #endif
 #else /* MS_WINDOWS */
     arg = !block;
     if (ioctlsocket(s->sock_fd, FIONBIO, &arg) != 0)
-        goto error;
+        goto done;
 #endif /* MS_WINDOWS */
+
+    result = 0;
+
+  done:
     Py_END_ALLOW_THREADS
 
-    return 0;
-  error:
+    if (result) {
 #ifndef MS_WINDOWS
-    PyErr_SetFromErrno(PyExc_OSError);
+        PyErr_SetFromErrno(PyExc_OSError);
 #else
-    PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
+        PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
 #endif
-    return -1;
+    }
+
+    return result;
 }
 
 static int