changeset 41478:d343d9ac173e

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
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 30 Jan 2019 13:08:59 -0800
parents ba7298160357
children 33560f3bbcd3
files tests/badserverext.py
diffstat 1 files changed, 21 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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