bpo-32454: socket closefd (#5048)
Add close(fd) function to the socket module Signed-off-by: Christian Heimes <christian@python.org>
This commit is contained in:
parent
2f050c7e1b
commit
d0e31b980f
@ -578,6 +578,14 @@ Other functions
|
|||||||
The :mod:`socket` module also offers various network-related services:
|
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)
|
.. 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
|
Translate the *host*/*port* argument into a sequence of 5-tuples that contain
|
||||||
|
@ -1519,6 +1519,22 @@ class GeneralModuleTests(unittest.TestCase):
|
|||||||
self.assertRaises(ValueError, fp.writable)
|
self.assertRaises(ValueError, fp.writable)
|
||||||
self.assertRaises(ValueError, fp.seekable)
|
self.assertRaises(ValueError, fp.seekable)
|
||||||
|
|
||||||
|
def test_socket_close(self):
|
||||||
|
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):
|
def test_makefile_mode(self):
|
||||||
for mode in 'r', 'rb', 'rw', 'w', 'wb':
|
for mode in 'r', 'rb', 'rw', 'w', 'wb':
|
||||||
with self.subTest(mode=mode):
|
with self.subTest(mode=mode):
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Add close(fd) function to the socket module.
|
@ -2836,7 +2836,7 @@ sock_close(PySocketSockObject *s)
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(close_doc,
|
PyDoc_STRVAR(sock_close_doc,
|
||||||
"close()\n\
|
"close()\n\
|
||||||
\n\
|
\n\
|
||||||
Close the socket. It cannot be used after this call.");
|
Close the socket. It cannot be used after this call.");
|
||||||
@ -4558,7 +4558,7 @@ static PyMethodDef sock_methods[] = {
|
|||||||
{"bind", (PyCFunction)sock_bind, METH_O,
|
{"bind", (PyCFunction)sock_bind, METH_O,
|
||||||
bind_doc},
|
bind_doc},
|
||||||
{"close", (PyCFunction)sock_close, METH_NOARGS,
|
{"close", (PyCFunction)sock_close, METH_NOARGS,
|
||||||
close_doc},
|
sock_close_doc},
|
||||||
{"connect", (PyCFunction)sock_connect, METH_O,
|
{"connect", (PyCFunction)sock_connect, METH_O,
|
||||||
connect_doc},
|
connect_doc},
|
||||||
{"connect_ex", (PyCFunction)sock_connect_ex, METH_O,
|
{"connect_ex", (PyCFunction)sock_connect_ex, METH_O,
|
||||||
@ -5456,6 +5456,31 @@ PyDoc_STRVAR(getprotobyname_doc,
|
|||||||
\n\
|
\n\
|
||||||
Return the protocol number for the named protocol. (Rarely used.)");
|
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
|
#ifndef NO_DUP
|
||||||
/* dup() function for socket fds */
|
/* dup() function for socket fds */
|
||||||
@ -6397,6 +6422,8 @@ static PyMethodDef socket_methods[] = {
|
|||||||
METH_VARARGS, getservbyport_doc},
|
METH_VARARGS, getservbyport_doc},
|
||||||
{"getprotobyname", socket_getprotobyname,
|
{"getprotobyname", socket_getprotobyname,
|
||||||
METH_VARARGS, getprotobyname_doc},
|
METH_VARARGS, getprotobyname_doc},
|
||||||
|
{"close", socket_close,
|
||||||
|
METH_O, close_doc},
|
||||||
#ifndef NO_DUP
|
#ifndef NO_DUP
|
||||||
{"dup", socket_dup,
|
{"dup", socket_dup,
|
||||||
METH_O, dup_doc},
|
METH_O, dup_doc},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user