Skip to content

Commit bccdc51

Browse files
committed
socket: workaround socket close problem
The socket implementation used to only call close on a socket when all references where gone. This works fine for cpython which uses reference counting but for pyston (and pypy) this is a problem. This works around the problem in a similar way as pypy does. It also uses the same method names so that 3th party libs which already support pypy will automatically work with pyston too. (e.g. urllib3)
1 parent f372724 commit bccdc51

25 files changed

+104
-25
lines changed

from_cpython/Lib/socket.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ class _closedsocket(object):
168168
__slots__ = []
169169
def _dummy(*args):
170170
raise error(EBADF, 'Bad file descriptor')
171+
172+
# Pyston change: socket close: add refcounting similar to pypy approach
173+
def _reuse(self):
174+
pass
175+
def _drop(self):
176+
pass
171177
# All _delegate_methods must also be initialized here.
172178
send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
173179
__getattr__ = _dummy
@@ -176,6 +182,9 @@ def _dummy(*args):
176182
# a platform-independent dup() functionality. The
177183
# implementation currently relies on reference counting
178184
# to close the underlying socket object.
185+
# Pyston change: socket close: we workaround the socket closing problem similar to pypy
186+
# by manually keeping track of the ref count.
187+
# When we switch to ref counting we should remove this changes!
179188
class _socketobject(object):
180189

181190
__doc__ = _realsocket.__doc__
@@ -185,13 +194,22 @@ class _socketobject(object):
185194
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
186195
if _sock is None:
187196
_sock = _realsocket(family, type, proto)
197+
198+
# Pyston change: socket close: add refcounting similar to pypys approach
199+
else:
200+
_sock._reuse()
201+
188202
self._sock = _sock
189203
for method in _delegate_methods:
190204
setattr(self, method, getattr(_sock, method))
191205

192206
def close(self, _closedsocket=_closedsocket,
193207
_delegate_methods=_delegate_methods, setattr=setattr):
194208
# This function should not reference any globals. See issue #808164.
209+
210+
# Pyston change: socket close: add refcounting similar to pypys approach
211+
self._sock._drop()
212+
195213
self._sock = _closedsocket()
196214
dummy = self._sock._dummy
197215
for method in _delegate_methods:
@@ -200,7 +218,13 @@ def close(self, _closedsocket=_closedsocket,
200218

201219
def accept(self):
202220
sock, addr = self._sock.accept()
203-
return _socketobject(_sock=sock), addr
221+
222+
# Pyston change: socket close: add refcounting similar to pypys approach
223+
# return _socketobject(_sock=sock), addr
224+
sockcopy = _socketobject(_sock=sock)
225+
sock._drop()
226+
return sockcopy, addr
227+
204228
accept.__doc__ = _realsocket.accept.__doc__
205229

206230
def dup(self):
@@ -245,6 +269,10 @@ class _fileobject(object):
245269

246270
def __init__(self, sock, mode='rb', bufsize=-1, close=False):
247271
self._sock = sock
272+
273+
# Pyston change: socket close: add refcounting similar to pypys approach
274+
sock._reuse()
275+
248276
self.mode = mode # Not actually used in this version
249277
if bufsize < 0:
250278
bufsize = self.default_bufsize
@@ -280,6 +308,11 @@ def close(self):
280308
finally:
281309
if self._close:
282310
self._sock.close()
311+
312+
# Pyston change: socket close: add refcounting similar to pypys approach
313+
else:
314+
self._sock._drop()
315+
283316
self._sock = None
284317

285318
def __del__(self):

from_cpython/Lib/ssl.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ def __init__(self, sock, keyfile=None, certfile=None,
156156
self.suppress_ragged_eofs = suppress_ragged_eofs
157157
self._makefile_refs = 0
158158

159+
# Pyston change: socket close: we have to decrease the socket refcount by calling close (pypy does the same)
160+
sock.close()
161+
159162
def read(self, len=1024):
160163

161164
"""Read up to LEN bytes and return them.
@@ -371,11 +374,21 @@ def makefile(self, mode='r', bufsize=-1):
371374
works with the SSL connection. Just use the code
372375
from the socket module."""
373376

374-
self._makefile_refs += 1
377+
# Pyston change: socket close: we increase the refcount inside _fileobject.__init__
378+
# self._makefile_refs += 1
379+
375380
# close=True so as to decrement the reference count when done with
376381
# the file-like object.
377382
return _fileobject(self, mode, bufsize, close=True)
378383

384+
# Pyston change: socket close: add refcounting similar to pypys approach
385+
def _reuse(self):
386+
self._makefile_refs += 1
387+
def _drop(self):
388+
if self._makefile_refs < 1:
389+
self.close()
390+
else:
391+
self._makefile_refs -= 1
379392

380393

381394
def wrap_socket(sock, keyfile=None, certfile=None,

from_cpython/Lib/test/test_asynchat.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
# test asynchat
32

43
import asyncore, asynchat, socket, time

from_cpython/Lib/test/test_asyncore.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
import asyncore
32
import unittest
43
import select

from_cpython/Lib/test/test_ftplib.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
"""Test script for ftplib module."""
32

43
# Modified by Giampaolo Rodola' to test FTP class, IPv6 and TLS

from_cpython/Lib/test/test_httplib.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
import httplib
32
import array
43
import httplib

from_cpython/Lib/test/test_poplib.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
"""Test script for poplib module."""
32

43
# Modified by Giampaolo Rodola' to give poplib.POP3 and poplib.POP3_SSL

from_cpython/Lib/test/test_ssl.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
# Test the support for SSL and sockets
32

43
import sys

from_cpython/Lib/test/test_telnetlib.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
import socket
32
import telnetlib
43
import time

from_cpython/Lib/test/test_urllib2net.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
import unittest
32
from test import test_support
43
from test.test_urllib2 import sanepathname2url

0 commit comments

Comments
 (0)