Skip to content

Commit d0e31b9

Browse files
authored
bpo-32454: socket closefd (#5048)
Add close(fd) function to the socket module Signed-off-by: Christian Heimes <christian@python.org>
1 parent 2f050c7 commit d0e31b9

4 files changed

Lines changed: 54 additions & 2 deletions

File tree

Doc/library/socket.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,14 @@ Other functions
578578
The :mod:`socket` module also offers various network-related services:
579579

580580

581+
.. function:: close(fd)
582+
583+
Close a socket file descriptor. This is like :func:`os.close`, but for
584+
sockets. On some platforms (most noticeable Windows) :func:`os.close`
585+
does not work for socket file descriptors.
586+
587+
.. versionadded:: 3.7
588+
581589
.. function:: getaddrinfo(host, port, family=0, type=0, proto=0, flags=0)
582590

583591
Translate the *host*/*port* argument into a sequence of 5-tuples that contain

Lib/test/test_socket.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,22 @@ def test_unusable_closed_socketio(self):
15191519
self.assertRaises(ValueError, fp.writable)
15201520
self.assertRaises(ValueError, fp.seekable)
15211521

1522+
def test_socket_close(self):
1523+
sock = socket.socket()
1524+
try:
1525+
sock.bind((HOST, 0))
1526+
socket.close(sock.fileno())
1527+
with self.assertRaises(OSError):
1528+
sock.listen(1)
1529+
finally:
1530+
with self.assertRaises(OSError):
1531+
# sock.close() fails with EBADF
1532+
sock.close()
1533+
with self.assertRaises(TypeError):
1534+
socket.close(None)
1535+
with self.assertRaises(OSError):
1536+
socket.close(-1)
1537+
15221538
def test_makefile_mode(self):
15231539
for mode in 'r', 'rb', 'rw', 'w', 'wb':
15241540
with self.subTest(mode=mode):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add close(fd) function to the socket module.

Modules/socketmodule.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2836,7 +2836,7 @@ sock_close(PySocketSockObject *s)
28362836
Py_RETURN_NONE;
28372837
}
28382838

2839-
PyDoc_STRVAR(close_doc,
2839+
PyDoc_STRVAR(sock_close_doc,
28402840
"close()\n\
28412841
\n\
28422842
Close the socket. It cannot be used after this call.");
@@ -4558,7 +4558,7 @@ static PyMethodDef sock_methods[] = {
45584558
{"bind", (PyCFunction)sock_bind, METH_O,
45594559
bind_doc},
45604560
{"close", (PyCFunction)sock_close, METH_NOARGS,
4561-
close_doc},
4561+
sock_close_doc},
45624562
{"connect", (PyCFunction)sock_connect, METH_O,
45634563
connect_doc},
45644564
{"connect_ex", (PyCFunction)sock_connect_ex, METH_O,
@@ -5456,6 +5456,31 @@ PyDoc_STRVAR(getprotobyname_doc,
54565456
\n\
54575457
Return the protocol number for the named protocol. (Rarely used.)");
54585458

5459+
static PyObject *
5460+
socket_close(PyObject *self, PyObject *fdobj)
5461+
{
5462+
SOCKET_T fd;
5463+
int res;
5464+
5465+
fd = PyLong_AsSocket_t(fdobj);
5466+
if (fd == (SOCKET_T)(-1) && PyErr_Occurred())
5467+
return NULL;
5468+
Py_BEGIN_ALLOW_THREADS
5469+
res = SOCKETCLOSE(fd);
5470+
Py_END_ALLOW_THREADS
5471+
/* bpo-30319: The peer can already have closed the connection.
5472+
Python ignores ECONNRESET on close(). */
5473+
if (res < 0 && !CHECK_ERRNO(ECONNRESET)) {
5474+
return set_error();
5475+
}
5476+
Py_RETURN_NONE;
5477+
}
5478+
5479+
PyDoc_STRVAR(close_doc,
5480+
"close(integer) -> None\n\
5481+
\n\
5482+
Close an integer socket file descriptor. This is like os.close(), but for\n\
5483+
sockets; on some platforms os.close() won't work for socket file descriptors.");
54595484

54605485
#ifndef NO_DUP
54615486
/* dup() function for socket fds */
@@ -6397,6 +6422,8 @@ static PyMethodDef socket_methods[] = {
63976422
METH_VARARGS, getservbyport_doc},
63986423
{"getprotobyname", socket_getprotobyname,
63996424
METH_VARARGS, getprotobyname_doc},
6425+
{"close", socket_close,
6426+
METH_O, close_doc},
64006427
#ifndef NO_DUP
64016428
{"dup", socket_dup,
64026429
METH_O, dup_doc},

0 commit comments

Comments
 (0)