Skip to content

Commit e198115

Browse files
committed
gh-89977: Keep the GIL for short socket and epoll control calls
1 parent 71f6c00 commit e198115

5 files changed

Lines changed: 26 additions & 11 deletions

File tree

‎Lib/test/test_epoll.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,16 @@ def test_unregister_closed(self):
238238
ep.unregister(fd)
239239
self.assertEqual(cm.exception.errno, errno.EBADF)
240240

241+
def test_unregister_twice(self):
242+
with select.epoll() as ep:
243+
ep.register(self.serverSocket)
244+
ep.unregister(self.serverSocket)
245+
with self.assertRaises(OSError) as cm:
246+
ep.unregister(self.serverSocket)
247+
self.assertEqual(cm.exception.errno, errno.ENOENT)
248+
ep.register(self.serverSocket)
249+
ep.unregister(self.serverSocket)
250+
241251
def test_close(self):
242252
open_file = open(__file__, "rb")
243253
self.addCleanup(open_file.close)

‎Lib/test/test_socket.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,18 @@ def requireSocket(*args):
945945

946946
class GeneralModuleTests(unittest.TestCase):
947947

948+
def test_socket_name_errors(self):
949+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
950+
sock.bind((socket_helper.HOSTv4, 0))
951+
self.assertGreater(sock.getsockname()[1], 0)
952+
with self.assertRaises(OSError):
953+
sock.getpeername()
954+
955+
with self.assertRaises(OSError):
956+
sock.getsockname()
957+
with self.assertRaises(OSError):
958+
sock.getpeername()
959+
948960
@unittest.skipUnless(_socket is not None, 'need _socket module')
949961
def test_socket_type(self):
950962
self.assertTrue(gc.is_tracked(_socket.socket))
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Avoid releasing the GIL for :meth:`socket.socket.setblocking`,
2+
:meth:`socket.socket.getsockname`, :meth:`socket.socket.getpeername`,
3+
:func:`socket.gethostname`, and :meth:`select.epoll.unregister`.

‎Modules/selectmodule.c‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,9 +1521,8 @@ pyepoll_internal_ctl(int epfd, int op, int fd, unsigned int events)
15211521
/* In kernel versions before 2.6.9, the EPOLL_CTL_DEL
15221522
* operation required a non-NULL pointer in event, even
15231523
* though this argument is ignored. */
1524-
Py_BEGIN_ALLOW_THREADS
1524+
/* Removing a watch is normally quick, so keep the GIL. */
15251525
result = epoll_ctl(epfd, op, fd, &ev);
1526-
Py_END_ALLOW_THREADS
15271526
break;
15281527
default:
15291528
result = -1;

‎Modules/socketmodule.c‎

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,6 @@ internal_setblocking(PySocketSockObject *s, int block)
828828
int delay_flag, new_delay_flag;
829829
#endif
830830

831-
Py_BEGIN_ALLOW_THREADS
832831
#ifndef MS_WINDOWS
833832
#if (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO))
834833
block = !block;
@@ -855,8 +854,6 @@ internal_setblocking(PySocketSockObject *s, int block)
855854
result = 0;
856855

857856
done:
858-
Py_END_ALLOW_THREADS
859-
860857
if (result) {
861858
#ifndef MS_WINDOWS
862859
PyErr_SetFromErrno(PyExc_OSError);
@@ -3915,9 +3912,7 @@ _socket_socket_getsockname_impl(PySocketSockObject *s)
39153912
if (!getsockaddrlen(s, &addrlen))
39163913
return NULL;
39173914
memset(&addrbuf, 0, addrlen);
3918-
Py_BEGIN_ALLOW_THREADS
39193915
res = getsockname(get_sock_fd(s), SAS2SA(&addrbuf), &addrlen);
3920-
Py_END_ALLOW_THREADS
39213916
if (res < 0)
39223917
return s->errorhandler();
39233918
return makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen,
@@ -3950,9 +3945,7 @@ _socket_socket_getpeername_impl(PySocketSockObject *s)
39503945
if (!getsockaddrlen(s, &addrlen))
39513946
return NULL;
39523947
memset(&addrbuf, 0, addrlen);
3953-
Py_BEGIN_ALLOW_THREADS
39543948
res = getpeername(get_sock_fd(s), SAS2SA(&addrbuf), &addrlen);
3955-
Py_END_ALLOW_THREADS
39563949
if (res < 0)
39573950
return s->errorhandler();
39583951
return makesockaddr(get_sock_fd(s), SAS2SA(&addrbuf), addrlen,
@@ -5968,9 +5961,7 @@ _socket_gethostname_impl(PyObject *module)
59685961
#else
59695962
char buf[1024];
59705963
int res;
5971-
Py_BEGIN_ALLOW_THREADS
59725964
res = gethostname(buf, (int) sizeof buf - 1);
5973-
Py_END_ALLOW_THREADS
59745965
if (res < 0)
59755966
return set_error();
59765967
buf[sizeof buf - 1] = '\0';

0 commit comments

Comments
 (0)