mirror of
https://github.com/python/cpython.git
synced 2025-07-30 22:54:16 +00:00
Release all forwarded functions in .close. Fixes #1513223.
This commit is contained in:
parent
a09803329c
commit
7596e8342e
3 changed files with 34 additions and 14 deletions
|
@ -130,35 +130,37 @@ _socketmethods = (
|
||||||
if sys.platform == "riscos":
|
if sys.platform == "riscos":
|
||||||
_socketmethods = _socketmethods + ('sleeptaskw',)
|
_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):
|
class _closedsocket(object):
|
||||||
__slots__ = []
|
__slots__ = []
|
||||||
def _dummy(*args):
|
def _dummy(*args):
|
||||||
raise error(EBADF, 'Bad file descriptor')
|
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):
|
class _socketobject(object):
|
||||||
|
|
||||||
__doc__ = _realsocket.__doc__
|
__doc__ = _realsocket.__doc__
|
||||||
|
|
||||||
__slots__ = ["_sock",
|
__slots__ = ["_sock", "__weakref__"] + list(_delegate_methods)
|
||||||
"recv", "recv_into", "recvfrom_into",
|
|
||||||
"send", "sendto", "recvfrom",
|
|
||||||
"__weakref__"]
|
|
||||||
|
|
||||||
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
|
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
|
||||||
if _sock is None:
|
if _sock is None:
|
||||||
_sock = _realsocket(family, type, proto)
|
_sock = _realsocket(family, type, proto)
|
||||||
self._sock = _sock
|
self._sock = _sock
|
||||||
self.send = self._sock.send
|
for method in _delegate_methods:
|
||||||
self.recv = self._sock.recv
|
setattr(self, method, getattr(_sock, method))
|
||||||
self.recv_into = self._sock.recv_into
|
|
||||||
self.sendto = self._sock.sendto
|
|
||||||
self.recvfrom = self._sock.recvfrom
|
|
||||||
self.recvfrom_into = self._sock.recvfrom_into
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self._sock = _closedsocket()
|
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__
|
close.__doc__ = _realsocket.close.__doc__
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
|
|
|
@ -582,6 +582,21 @@ class BasicUDPTest(ThreadedUDPSocketTest):
|
||||||
def _testRecvFrom(self):
|
def _testRecvFrom(self):
|
||||||
self.cli.sendto(MSG, 0, (HOST, PORT))
|
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):
|
class BasicSocketPairTest(SocketPairTest):
|
||||||
|
|
||||||
def __init__(self, methodName='runTest'):
|
def __init__(self, methodName='runTest'):
|
||||||
|
@ -890,8 +905,8 @@ class BufferIOTest(SocketConnectedTest):
|
||||||
self.serv_conn.send(buf)
|
self.serv_conn.send(buf)
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
tests = [GeneralModuleTests, BasicTCPTest, TCPTimeoutTest, TestExceptions,
|
tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest,
|
||||||
BufferIOTest]
|
TestExceptions, BufferIOTest]
|
||||||
if sys.platform != 'mac':
|
if sys.platform != 'mac':
|
||||||
tests.extend([ BasicUDPTest, UDPTimeoutTest ])
|
tests.extend([ BasicUDPTest, UDPTimeoutTest ])
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,9 @@ Core and builtins
|
||||||
Library
|
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
|
- The '_ctypes' extension module now works when Python is configured
|
||||||
with the --without-threads option.
|
with the --without-threads option.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue