[pypy-commit] pypy default: Fix issue #1492.

arigo noreply at buildbot.pypy.org
Fri May 31 10:22:00 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r64675:d439d104a605
Date: 2013-05-31 10:21 +0200
http://bitbucket.org/pypy/pypy/changeset/d439d104a605/

Log:	Fix issue #1492.

	Manual revert in socket.py. This re-introduces the change done in
	2006 in 9db062bb60e3 (anders, implementing explicit refcounting on
	the underlying _socket.socket objects). It reverts a later change
	where, I think for goals of being more Python3-like, the refcounter
	was moved to the class socket._socketobject. However this later
	change is less compatible with CPython 2.x, as shown by eventlet.

diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py
--- a/lib-python/2.7/socket.py
+++ b/lib-python/2.7/socket.py
@@ -96,6 +96,7 @@
 
 
 _realsocket = socket
+_type = type
 
 # WSA error codes
 if sys.platform.lower().startswith("win"):
@@ -173,12 +174,18 @@
 
     __doc__ = _realsocket.__doc__
 
+    __slots__ = ["_sock", "__weakref__"]
+
     def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
         if _sock is None:
             _sock = _realsocket(family, type, proto)
+        elif _type(_sock) is _realsocket:
+            _sock._reuse()
+        # PyPy note about refcounting: implemented with _reuse()/_drop()
+        # on the class '_socket.socket'.  Python 3 did it differently
+        # with a reference counter on this class 'socket._socketobject'
+        # instead, but it is a less compatible change (breaks eventlet).
         self._sock = _sock
-        self._io_refs = 0
-        self._closed = False
 
     def send(self, data, flags=0):
         return self._sock.send(data, flags=flags)
@@ -208,7 +215,9 @@
     sendto.__doc__ = _realsocket.sendto.__doc__
 
     def close(self):
-        # This function should not reference any globals. See issue #808164.
+        s = self._sock
+        if type(s) is _realsocket:
+            s._drop()
         self._sock = _closedsocket()
     close.__doc__ = _realsocket.close.__doc__
 
@@ -228,24 +237,7 @@
 
         Return a regular file object corresponding to the socket.  The mode
         and bufsize arguments are as for the built-in open() function."""
-        self._io_refs += 1
-        return _fileobject(self, mode, bufsize)
-
-    def _decref_socketios(self):
-        if self._io_refs > 0:
-            self._io_refs -= 1
-        if self._closed:
-            self.close()
-
-    def _real_close(self):
-        # This function should not reference any globals. See issue #808164.
-        self._sock.close()
-
-    def close(self):
-        # This function should not reference any globals. See issue #808164.
-        self._closed = True
-        if self._io_refs <= 0:
-            self._real_close()
+        return _fileobject(self._sock, mode, bufsize)
 
     family = property(lambda self: self._sock.family, doc="the socket family")
     type = property(lambda self: self._sock.type, doc="the socket type")
@@ -286,6 +278,8 @@
                  "_close"]
 
     def __init__(self, sock, mode='rb', bufsize=-1, close=False):
+        if type(sock) is _realsocket:
+            sock._reuse()
         self._sock = sock
         self.mode = mode # Not actually used in this version
         if bufsize < 0:
@@ -320,16 +314,11 @@
             if self._sock:
                 self.flush()
         finally:
-            if self._sock:
-                if self._close:
-                    self._sock.close()
-                else:
-                    try:
-                        self._sock._decref_socketios()
-                    except AttributeError:
-                        pass  # bah, someone built a _fileobject manually
-                              # with some unexpected replacement of the
-                              # _socketobject class
+            s = self._sock
+            if type(s) is _realsocket:
+                s._drop()
+            if self._close:
+                self._sock.close()
             self._sock = None
 
     def __del__(self):


More information about the pypy-commit mailing list