Index: Modules/socketmodule.c =================================================================== --- Modules/socketmodule.c (révision 68329) +++ Modules/socketmodule.c (copie de travail) @@ -1548,6 +1548,14 @@ } } +static int +sock_check_closed(PySocketSockObject *s) +{ + if (0 <= s->sock_fd) + return 0; + PyErr_SetString(socket_error, "I/O operation on closed socket"); + return 1; +} /* s._accept() -> (fd, address) */ @@ -1562,6 +1570,8 @@ PyObject *res = NULL; int timeout; + if (sock_check_closed(s)) + return NULL; if (!getsockaddrlen(s, &addrlen)) return NULL; memset(&addrbuf, 0, addrlen); @@ -1710,6 +1720,8 @@ int buflen; int flag; + if (sock_check_closed(s)) + return NULL; if (PyArg_ParseTuple(args, "iii:setsockopt", &level, &optname, &flag)) { buf = (char *) &flag; @@ -1749,6 +1761,8 @@ PyObject *buf; socklen_t buflen = 0; + if (sock_check_closed(s)) + return NULL; if (!PyArg_ParseTuple(args, "ii|i:getsockopt", &level, &optname, &buflen)) return NULL; @@ -1944,6 +1958,8 @@ int res; int timeout; + if (sock_check_closed(s)) + return NULL; if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) return NULL; @@ -1978,6 +1994,8 @@ int res; int timeout; + if (sock_check_closed(s)) + return NULL; if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) return NULL; @@ -2001,12 +2019,13 @@ This is like connect(address), but returns an error code (the errno value)\n\ instead of raising an exception when an error occurs."); - /* s.fileno() method */ static PyObject * sock_fileno(PySocketSockObject *s) { + if (sock_check_closed(s)) + return NULL; return PyLong_FromSocket_t(s->sock_fd); } @@ -2025,6 +2044,8 @@ int res; socklen_t addrlen; + if (sock_check_closed(s)) + return NULL; if (!getsockaddrlen(s, &addrlen)) return NULL; memset(&addrbuf, 0, addrlen); @@ -2054,6 +2075,8 @@ int res; socklen_t addrlen; + if (sock_check_closed(s)) + return NULL; if (!getsockaddrlen(s, &addrlen)) return NULL; memset(&addrbuf, 0, addrlen); @@ -2083,6 +2106,8 @@ int backlog; int res; + if (sock_check_closed(s)) + return NULL; backlog = PyLong_AsLong(arg); if (backlog == -1 && PyErr_Occurred()) return NULL; @@ -2202,6 +2227,8 @@ ssize_t outlen; PyObject *buf; + if (sock_check_closed(s)) + return NULL; if (!PyArg_ParseTuple(args, "i|i:recv", &recvlen, &flags)) return NULL; @@ -2255,6 +2282,8 @@ char *buf; int buflen; + if (sock_check_closed(s)) + return NULL; /* Get the buffer's memory */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ii:recv_into", kwlist, &pbuf, &recvlen, &flags)) @@ -2381,6 +2410,8 @@ int recvlen, flags = 0; ssize_t outlen; + if (sock_check_closed(s)) + return NULL; if (!PyArg_ParseTuple(args, "i|i:recvfrom", &recvlen, &flags)) return NULL; @@ -2437,6 +2468,8 @@ PyObject *addr = NULL; + if (sock_check_closed(s)) + return NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ii:recvfrom_into", kwlist, &pbuf, &recvlen, &flags)) @@ -2485,6 +2518,8 @@ int len, n = -1, flags = 0, timeout; Py_buffer pbuf; + if (sock_check_closed(s)) + return NULL; if (!PyArg_ParseTuple(args, "y*|i:send", &pbuf, &flags)) return NULL; @@ -2533,6 +2568,8 @@ int len, n = -1, flags = 0, timeout; Py_buffer pbuf; + if (sock_check_closed(s)) + return NULL; if (!PyArg_ParseTuple(args, "y*|i:sendall", &pbuf, &flags)) return NULL; buf = pbuf.buf; @@ -2594,6 +2631,8 @@ sock_addr_t addrbuf; int addrlen, n = -1, flags, timeout; + if (sock_check_closed(s)) + return NULL; flags = 0; if (!PyArg_ParseTuple(args, "y*O:sendto", &pbuf, &addro)) { PyErr_Clear(); @@ -2645,6 +2684,8 @@ int how; int res; + if (sock_check_closed(s)) + return NULL; how = PyLong_AsLong(arg); if (how == -1 && PyErr_Occurred()) return NULL; @@ -2671,6 +2712,8 @@ unsigned int option = RCVALL_ON; DWORD recv; + if (sock_check_closed(s)) + return NULL; if (!PyArg_ParseTuple(arg, "kI:ioctl", &cmd, &option)) return NULL; Index: Lib/test/test_socket.py =================================================================== --- Lib/test/test_socket.py (révision 68329) +++ Lib/test/test_socket.py (copie de travail) @@ -522,6 +522,37 @@ self.assert_(hasattr(socket, 'RCVALL_ON')) self.assert_(hasattr(socket, 'RCVALL_OFF')) + def assertClosedError(self, func, *args): + try: + func(*args) + self.assert_(False, "socket.error not raised") + except socket.error as err: + self.assertEquals(str(err), "I/O operation on closed socket") + + def testClosed(self): + test = self.assertClosedError + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.close() + + test(s.fileno) + test(s.getsockname) + test(s.getpeername) + test(s.accept) + test(s.connect, (HOST, 80)) + test(s.getsockopt, socket.SOL_SOCKET, socket.SO_REUSEADDR) + if hasattr(s, "ioctl"): + test(s.ioctl, socket.SIO_RCVALL, socket.RCVALL_ON) + test(s.listen, 1) + test(s.makefile, "r") + test(s.recv, 1) + test(s.recvfrom, 1) + test(s.recvfrom_into, bytearray(1), 1) + test(s.send, b"a") + test(s.sendall, b"a") + test(s.sendto, b"a", (HOST, 22)) + test(s.setsockopt, socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + test(s.shutdown, socket.SHUT_RDWR) class BasicTCPTest(SocketConnectedTest):