# HG changeset patch # User Gregory Szorc # Date 1548882539 28800 # Node ID d343d9ac173e425ce212ca97384e47a6cdde3505 # Parent ba729816035790ad2e99d3fc451c4a4af222837f tests: change how sockets are closed Python 3 uses a different type to represent a socket file object than Python 2. We need to conditionalize how the socket is closed accordingly. While we're here, we switch to use socket.shutdown() to close the socket. This is because socket.close() may not actually close the socket until it is GCd. socket.shutdown() forces an immediate shutdown. I suspect Python 3 changed semantic behavior here, as I can't get test-http-bad-server.t to work with socket.close(). socket.shutdown() does appear to work, however. Differential Revision: https://phab.mercurial-scm.org/D5751 diff -r ba7298160357 -r d343d9ac173e tests/badserverext.py --- a/tests/badserverext.py Wed Jan 30 09:52:16 2019 -0800 +++ b/tests/badserverext.py Wed Jan 30 13:08:59 2019 -0800 @@ -34,6 +34,7 @@ import socket from mercurial import( + pycompat, registrar, ) @@ -115,7 +116,7 @@ object.__setattr__(self, '_closeaftersendbytes', closeaftersendbytes) def __getattribute__(self, name): - if name in ('read', 'readline', 'write', '_writelog'): + if name in ('_close', 'read', 'readline', 'write', '_writelog'): return object.__getattribute__(self, name) return getattr(object.__getattribute__(self, '_orig'), name) @@ -133,6 +134,19 @@ object.__getattribute__(self, '_logfp').write(b'\n') object.__getattribute__(self, '_logfp').flush() + def _close(self): + # Python 3 uses an io.BufferedIO instance. Python 2 uses some file + # object wrapper. + if pycompat.ispy3: + orig = object.__getattribute__(self, '_orig') + + if hasattr(orig, 'raw'): + orig.raw._sock.shutdown(socket.SHUT_RDWR) + else: + self.close() + else: + self._sock.shutdown(socket.SHUT_RDWR) + def read(self, size=-1): remaining = object.__getattribute__(self, '_closeafterrecvbytes') @@ -161,7 +175,8 @@ if remaining <= 0: self._writelog(b'read limit reached, closing socket') - self._sock.close() + self._close() + # This is the easiest way to abort the current request. raise Exception('connection closed after receiving N bytes') @@ -194,7 +209,8 @@ if remaining <= 0: self._writelog(b'read limit reached; closing socket') - self._sock.close() + self._close() + # This is the easiest way to abort the current request. raise Exception('connection closed after receiving N bytes') @@ -225,7 +241,8 @@ if remaining <= 0: self._writelog(b'write limit reached; closing socket') - self._sock.close() + self._close() + raise Exception('connection closed after sending N bytes') return result