Commit 1d79fb60 authored by Yury Selivanov's avatar Yury Selivanov

Issue #28471: Fix crash (GIL state related) in socket.setblocking

parent 3fbaf724
...@@ -4552,6 +4552,18 @@ class TestExceptions(unittest.TestCase): ...@@ -4552,6 +4552,18 @@ class TestExceptions(unittest.TestCase):
self.assertTrue(issubclass(socket.gaierror, OSError)) self.assertTrue(issubclass(socket.gaierror, OSError))
self.assertTrue(issubclass(socket.timeout, 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') @unittest.skipUnless(sys.platform == 'linux', 'Linux specific test')
class TestLinuxAbstractNamespace(unittest.TestCase): class TestLinuxAbstractNamespace(unittest.TestCase):
......
...@@ -13,6 +13,10 @@ Core and Builtins ...@@ -13,6 +13,10 @@ Core and Builtins
- Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception - Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
loss in PyTraceBack_Here(). loss in PyTraceBack_Here().
- Issue #28471: Fix "Python memory allocator called without holding the GIL"
crash in socket.setblocking.
Library Library
------- -------
......
...@@ -622,6 +622,7 @@ set_gaierror(int error) ...@@ -622,6 +622,7 @@ set_gaierror(int error)
static int static int
internal_setblocking(PySocketSockObject *s, int block) internal_setblocking(PySocketSockObject *s, int block)
{ {
int result = -1;
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
u_long arg; u_long arg;
#endif #endif
...@@ -641,34 +642,39 @@ internal_setblocking(PySocketSockObject *s, int block) ...@@ -641,34 +642,39 @@ internal_setblocking(PySocketSockObject *s, int block)
#if (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO)) #if (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO))
block = !block; block = !block;
if (ioctl(s->sock_fd, FIONBIO, (unsigned int *)&block) == -1) if (ioctl(s->sock_fd, FIONBIO, (unsigned int *)&block) == -1)
goto error; goto done;
#else #else
delay_flag = fcntl(s->sock_fd, F_GETFL, 0); delay_flag = fcntl(s->sock_fd, F_GETFL, 0);
if (delay_flag == -1) if (delay_flag == -1)
goto error; goto done;
if (block) if (block)
new_delay_flag = delay_flag & (~O_NONBLOCK); new_delay_flag = delay_flag & (~O_NONBLOCK);
else else
new_delay_flag = delay_flag | O_NONBLOCK; new_delay_flag = delay_flag | O_NONBLOCK;
if (new_delay_flag != delay_flag) if (new_delay_flag != delay_flag)
if (fcntl(s->sock_fd, F_SETFL, new_delay_flag) == -1) if (fcntl(s->sock_fd, F_SETFL, new_delay_flag) == -1)
goto error; goto done;
#endif #endif
#else /* MS_WINDOWS */ #else /* MS_WINDOWS */
arg = !block; arg = !block;
if (ioctlsocket(s->sock_fd, FIONBIO, &arg) != 0) if (ioctlsocket(s->sock_fd, FIONBIO, &arg) != 0)
goto error; goto done;
#endif /* MS_WINDOWS */ #endif /* MS_WINDOWS */
result = 0;
done:
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
return 0; if (result) {
error:
#ifndef MS_WINDOWS #ifndef MS_WINDOWS
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
#else #else
PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
#endif #endif
return -1; }
return result;
} }
static int static int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment