Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Doc/library/socket.rst
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,14 @@ Other functions
The :mod:`socket` module also offers various network-related services:


.. function:: close(fd)

Close a socket file descriptor. This is like :func:`os.close`, but for
sockets. On some platforms (most noticeable Windows) :func:`os.close`
does not work for socket file descriptors.

.. versionadded:: 3.7

.. function:: getaddrinfo(host, port, family=0, type=0, proto=0, flags=0)

Translate the *host*/*port* argument into a sequence of 5-tuples that contain
Expand Down
16 changes: 16 additions & 0 deletions Lib/test/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,22 @@ def test_unusable_closed_socketio(self):
self.assertRaises(ValueError, fp.writable)
self.assertRaises(ValueError, fp.seekable)

def test_socket_close(self):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there already a test for dup()?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping on this question.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there is no test. I don't have time to write a test case, Would you like me to drop the documentation for dup?

sock = socket.socket()
try:
sock.bind((HOST, 0))
socket.close(sock.fileno())
with self.assertRaises(OSError):
sock.listen(1)
finally:
with self.assertRaises(OSError):
# sock.close() fails with EBADF
sock.close()
with self.assertRaises(TypeError):
socket.close(None)
with self.assertRaises(OSError):
socket.close(-1)

def test_makefile_mode(self):
for mode in 'r', 'rb', 'rw', 'w', 'wb':
with self.subTest(mode=mode):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add close(fd) function to the socket module.
31 changes: 29 additions & 2 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2836,7 +2836,7 @@ sock_close(PySocketSockObject *s)
Py_RETURN_NONE;
}

PyDoc_STRVAR(close_doc,
PyDoc_STRVAR(sock_close_doc,
"close()\n\
\n\
Close the socket. It cannot be used after this call.");
Expand Down Expand Up @@ -4558,7 +4558,7 @@ static PyMethodDef sock_methods[] = {
{"bind", (PyCFunction)sock_bind, METH_O,
bind_doc},
{"close", (PyCFunction)sock_close, METH_NOARGS,
close_doc},
sock_close_doc},
{"connect", (PyCFunction)sock_connect, METH_O,
connect_doc},
{"connect_ex", (PyCFunction)sock_connect_ex, METH_O,
Expand Down Expand Up @@ -5456,6 +5456,31 @@ PyDoc_STRVAR(getprotobyname_doc,
\n\
Return the protocol number for the named protocol. (Rarely used.)");

static PyObject *
socket_close(PyObject *self, PyObject *fdobj)
{
SOCKET_T fd;
int res;

fd = PyLong_AsSocket_t(fdobj);
if (fd == (SOCKET_T)(-1) && PyErr_Occurred())
return NULL;
Py_BEGIN_ALLOW_THREADS
res = SOCKETCLOSE(fd);
Py_END_ALLOW_THREADS
/* bpo-30319: The peer can already have closed the connection.
Python ignores ECONNRESET on close(). */
if (res < 0 && !CHECK_ERRNO(ECONNRESET)) {
return set_error();
}
Py_RETURN_NONE;
}

PyDoc_STRVAR(close_doc,
"close(integer) -> None\n\
\n\
Close an integer socket file descriptor. This is like os.close(), but for\n\
sockets; on some platforms os.close() won't work for socket file descriptors.");

#ifndef NO_DUP
/* dup() function for socket fds */
Expand Down Expand Up @@ -6397,6 +6422,8 @@ static PyMethodDef socket_methods[] = {
METH_VARARGS, getservbyport_doc},
{"getprotobyname", socket_getprotobyname,
METH_VARARGS, getprotobyname_doc},
{"close", socket_close,
METH_O, close_doc},
#ifndef NO_DUP
{"dup", socket_dup,
METH_O, dup_doc},
Expand Down