diff options
author | Martin v. Löwis <martin@v.loewis.de> | 2006-07-01 15:33:37 (GMT) |
---|---|---|
committer | Martin v. Löwis <martin@v.loewis.de> | 2006-07-01 15:33:37 (GMT) |
commit | 7596e8342ea34108d773d1802d5147e9884b547f (patch) | |
tree | aa19561ab430e4a5b9edee0409ceb4943339edd6 | |
parent | a09803329c6315792a9dee92c9d4d9bfe6eab01a (diff) | |
download | cpython-7596e8342ea34108d773d1802d5147e9884b547f.zip cpython-7596e8342ea34108d773d1802d5147e9884b547f.tar.gz cpython-7596e8342ea34108d773d1802d5147e9884b547f.tar.bz2 |
Release all forwarded functions in .close. Fixes #1513223.
-rw-r--r-- | Lib/socket.py | 26 | ||||
-rw-r--r-- | Lib/test/test_socket.py | 19 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
3 files changed, 34 insertions, 14 deletions
diff --git a/Lib/socket.py b/Lib/socket.py index fa0e663..4e83f09 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -130,35 +130,37 @@ _socketmethods = ( if sys.platform == "riscos": _socketmethods = _socketmethods + ('sleeptaskw',) +# All the method names that must be delegated to either the real socket +# object or the _closedsocket object. +_delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into", + "send", "sendto") + class _closedsocket(object): __slots__ = [] def _dummy(*args): raise error(EBADF, 'Bad file descriptor') - send = recv = sendto = recvfrom = __getattr__ = _dummy + # All _delegate_methods must also be initialized here. + send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy + __getattr__ = _dummy class _socketobject(object): __doc__ = _realsocket.__doc__ - __slots__ = ["_sock", - "recv", "recv_into", "recvfrom_into", - "send", "sendto", "recvfrom", - "__weakref__"] + __slots__ = ["_sock", "__weakref__"] + list(_delegate_methods) def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None): if _sock is None: _sock = _realsocket(family, type, proto) self._sock = _sock - self.send = self._sock.send - self.recv = self._sock.recv - self.recv_into = self._sock.recv_into - self.sendto = self._sock.sendto - self.recvfrom = self._sock.recvfrom - self.recvfrom_into = self._sock.recvfrom_into + for method in _delegate_methods: + setattr(self, method, getattr(_sock, method)) def close(self): self._sock = _closedsocket() - self.send = self.recv = self.sendto = self.recvfrom = self._sock._dummy + dummy = self._sock._dummy + for method in _delegate_methods: + setattr(self, method, dummy) close.__doc__ = _realsocket.close.__doc__ def accept(self): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index e773eab..b7d3916 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -582,6 +582,21 @@ class BasicUDPTest(ThreadedUDPSocketTest): def _testRecvFrom(self): self.cli.sendto(MSG, 0, (HOST, PORT)) +class TCPCloserTest(ThreadedTCPSocketTest): + + def testClose(self): + conn, addr = self.serv.accept() + conn.close() + + sd = self.cli + read, write, err = select.select([sd], [], [], 1.0) + self.assertEqual(read, [sd]) + self.assertEqual(sd.recv(1), '') + + def _testClose(self): + self.cli.connect((HOST, PORT)) + time.sleep(1.0) + class BasicSocketPairTest(SocketPairTest): def __init__(self, methodName='runTest'): @@ -890,8 +905,8 @@ class BufferIOTest(SocketConnectedTest): self.serv_conn.send(buf) def test_main(): - tests = [GeneralModuleTests, BasicTCPTest, TCPTimeoutTest, TestExceptions, - BufferIOTest] + tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, + TestExceptions, BufferIOTest] if sys.platform != 'mac': tests.extend([ BasicUDPTest, UDPTimeoutTest ]) @@ -19,6 +19,9 @@ Core and builtins Library ------- +- Bug #1513223: .close() of a _socketobj now releases the underlying + socket again, which then gets closed as it becomes unreferenced. + - The '_ctypes' extension module now works when Python is configured with the --without-threads option. |