Commit e46c0597 authored by Marius Wachtler's avatar Marius Wachtler

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)
parent f3727242
...@@ -168,6 +168,12 @@ class _closedsocket(object): ...@@ -168,6 +168,12 @@ class _closedsocket(object):
__slots__ = [] __slots__ = []
def _dummy(*args): def _dummy(*args):
raise error(EBADF, 'Bad file descriptor') raise error(EBADF, 'Bad file descriptor')
# Pyston change: socket close: add refcounting similar to pypy approach
def _reuse(self):
pass
def _drop(self):
pass
# All _delegate_methods must also be initialized here. # All _delegate_methods must also be initialized here.
send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
__getattr__ = _dummy __getattr__ = _dummy
...@@ -176,6 +182,9 @@ class _closedsocket(object): ...@@ -176,6 +182,9 @@ class _closedsocket(object):
# a platform-independent dup() functionality. The # a platform-independent dup() functionality. The
# implementation currently relies on reference counting # implementation currently relies on reference counting
# to close the underlying socket object. # to close the underlying socket object.
# Pyston change: socket close: we workaround the socket closing problem similar to pypy
# by manually keeping track of the ref count.
# When we switch to ref counting we should remove this changes!
class _socketobject(object): class _socketobject(object):
__doc__ = _realsocket.__doc__ __doc__ = _realsocket.__doc__
...@@ -185,6 +194,11 @@ class _socketobject(object): ...@@ -185,6 +194,11 @@ class _socketobject(object):
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)
# Pyston change: socket close: add refcounting similar to pypys approach
else:
_sock._reuse()
self._sock = _sock self._sock = _sock
for method in _delegate_methods: for method in _delegate_methods:
setattr(self, method, getattr(_sock, method)) setattr(self, method, getattr(_sock, method))
...@@ -192,6 +206,10 @@ class _socketobject(object): ...@@ -192,6 +206,10 @@ class _socketobject(object):
def close(self, _closedsocket=_closedsocket, def close(self, _closedsocket=_closedsocket,
_delegate_methods=_delegate_methods, setattr=setattr): _delegate_methods=_delegate_methods, setattr=setattr):
# This function should not reference any globals. See issue #808164. # This function should not reference any globals. See issue #808164.
# Pyston change: socket close: add refcounting similar to pypys approach
self._sock._drop()
self._sock = _closedsocket() self._sock = _closedsocket()
dummy = self._sock._dummy dummy = self._sock._dummy
for method in _delegate_methods: for method in _delegate_methods:
...@@ -200,7 +218,13 @@ class _socketobject(object): ...@@ -200,7 +218,13 @@ class _socketobject(object):
def accept(self): def accept(self):
sock, addr = self._sock.accept() sock, addr = self._sock.accept()
return _socketobject(_sock=sock), addr
# Pyston change: socket close: add refcounting similar to pypys approach
# return _socketobject(_sock=sock), addr
sockcopy = _socketobject(_sock=sock)
sock._drop()
return sockcopy, addr
accept.__doc__ = _realsocket.accept.__doc__ accept.__doc__ = _realsocket.accept.__doc__
def dup(self): def dup(self):
...@@ -245,6 +269,10 @@ class _fileobject(object): ...@@ -245,6 +269,10 @@ class _fileobject(object):
def __init__(self, sock, mode='rb', bufsize=-1, close=False): def __init__(self, sock, mode='rb', bufsize=-1, close=False):
self._sock = sock self._sock = sock
# Pyston change: socket close: add refcounting similar to pypys approach
sock._reuse()
self.mode = mode # Not actually used in this version self.mode = mode # Not actually used in this version
if bufsize < 0: if bufsize < 0:
bufsize = self.default_bufsize bufsize = self.default_bufsize
...@@ -280,6 +308,11 @@ class _fileobject(object): ...@@ -280,6 +308,11 @@ class _fileobject(object):
finally: finally:
if self._close: if self._close:
self._sock.close() self._sock.close()
# Pyston change: socket close: add refcounting similar to pypys approach
else:
self._sock._drop()
self._sock = None self._sock = None
def __del__(self): def __del__(self):
......
...@@ -156,6 +156,9 @@ class SSLSocket(socket): ...@@ -156,6 +156,9 @@ class SSLSocket(socket):
self.suppress_ragged_eofs = suppress_ragged_eofs self.suppress_ragged_eofs = suppress_ragged_eofs
self._makefile_refs = 0 self._makefile_refs = 0
# Pyston change: socket close: we have to decrease the socket refcount by calling close (pypy does the same)
sock.close()
def read(self, len=1024): def read(self, len=1024):
"""Read up to LEN bytes and return them. """Read up to LEN bytes and return them.
...@@ -371,11 +374,21 @@ class SSLSocket(socket): ...@@ -371,11 +374,21 @@ class SSLSocket(socket):
works with the SSL connection. Just use the code works with the SSL connection. Just use the code
from the socket module.""" from the socket module."""
self._makefile_refs += 1 # Pyston change: socket close: we increase the refcount inside _fileobject.__init__
# self._makefile_refs += 1
# close=True so as to decrement the reference count when done with # close=True so as to decrement the reference count when done with
# the file-like object. # the file-like object.
return _fileobject(self, mode, bufsize, close=True) return _fileobject(self, mode, bufsize, close=True)
# Pyston change: socket close: add refcounting similar to pypys approach
def _reuse(self):
self._makefile_refs += 1
def _drop(self):
if self._makefile_refs < 1:
self.close()
else:
self._makefile_refs -= 1
def wrap_socket(sock, keyfile=None, certfile=None, def wrap_socket(sock, keyfile=None, certfile=None,
......
# expected: fail
# test asynchat # test asynchat
import asyncore, asynchat, socket, time import asyncore, asynchat, socket, time
......
# expected: fail
import asyncore import asyncore
import unittest import unittest
import select import select
......
# expected: fail
"""Test script for ftplib module.""" """Test script for ftplib module."""
# Modified by Giampaolo Rodola' to test FTP class, IPv6 and TLS # Modified by Giampaolo Rodola' to test FTP class, IPv6 and TLS
......
# expected: fail
import httplib import httplib
import array import array
import httplib import httplib
......
# expected: fail
"""Test script for poplib module.""" """Test script for poplib module."""
# Modified by Giampaolo Rodola' to give poplib.POP3 and poplib.POP3_SSL # Modified by Giampaolo Rodola' to give poplib.POP3 and poplib.POP3_SSL
......
# expected: fail
# Test the support for SSL and sockets # Test the support for SSL and sockets
import sys import sys
......
# expected: fail
import socket import socket
import telnetlib import telnetlib
import time import time
......
# expected: fail
import unittest import unittest
from test import test_support from test import test_support
from test.test_urllib2 import sanepathname2url from test.test_urllib2 import sanepathname2url
......
# expected: fail
import unittest import unittest
from test import test_support from test import test_support
......
...@@ -1200,6 +1200,11 @@ class AbstractHTTPHandler(BaseHandler): ...@@ -1200,6 +1200,11 @@ class AbstractHTTPHandler(BaseHandler):
# out of socket._fileobject() and into a base class. # out of socket._fileobject() and into a base class.
r.recv = r.read r.recv = r.read
# Pyston change: socket close: add refcounting similar to pypys approach
r._reuse = lambda: None
r._drop = lambda: None
fp = socket._fileobject(r, close=True) fp = socket._fileobject(r, close=True)
resp = addinfourl(fp, r.msg, req.get_full_url()) resp = addinfourl(fp, r.msg, req.get_full_url())
......
...@@ -789,6 +789,9 @@ init_sockobject(PySocketSockObject *s, ...@@ -789,6 +789,9 @@ init_sockobject(PySocketSockObject *s,
s->errorhandler = &set_error; s->errorhandler = &set_error;
// Pyston change: socket close: add refcounting similar to pypys approach
s->close_ref_count = 1;
if (defaulttimeout >= 0.0) if (defaulttimeout >= 0.0)
internal_setblocking(s, 0); internal_setblocking(s, 0);
...@@ -2983,6 +2986,21 @@ sock_shutdown(PySocketSockObject *s, PyObject *arg) ...@@ -2983,6 +2986,21 @@ sock_shutdown(PySocketSockObject *s, PyObject *arg)
return Py_None; return Py_None;
} }
// Pyston change: socket close: add refcounting similar to pypys approach
static PyObject *
sock_reuse(PySocketSockObject *s) {
assert(s->close_ref_count > 0);
++s->close_ref_count;
return Py_None;
}
static PyObject *
sock_drop(PySocketSockObject *s) {
--s->close_ref_count;
if (s->close_ref_count <= 0)
sock_close(s);
return Py_None;
}
PyDoc_STRVAR(shutdown_doc, PyDoc_STRVAR(shutdown_doc,
"shutdown(flag)\n\ "shutdown(flag)\n\
\n\ \n\
...@@ -3099,6 +3117,11 @@ static PyMethodDef sock_methods[] = { ...@@ -3099,6 +3117,11 @@ static PyMethodDef sock_methods[] = {
{"sleeptaskw", (PyCFunction)sock_sleeptaskw, METH_O, {"sleeptaskw", (PyCFunction)sock_sleeptaskw, METH_O,
sleeptaskw_doc}, sleeptaskw_doc},
#endif #endif
// Pyston change: socket close: add refcounting similar to pypys approach
{"_reuse", (PyCFunction)sock_reuse, METH_NOARGS, NULL},
{"_drop", (PyCFunction)sock_drop, METH_NOARGS, NULL},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
......
...@@ -132,6 +132,9 @@ typedef struct { ...@@ -132,6 +132,9 @@ typedef struct {
sets a Python exception */ sets a Python exception */
double sock_timeout; /* Operation timeout in seconds; double sock_timeout; /* Operation timeout in seconds;
0.0 means non-blocking */ 0.0 means non-blocking */
// Pyston change: socket close: add refcounting similar to pypys approach
int close_ref_count;
} PySocketSockObject; } PySocketSockObject;
/* --- C API ----------------------------------------------------*/ /* --- C API ----------------------------------------------------*/
......
...@@ -24,8 +24,6 @@ test_al No module named al ...@@ -24,8 +24,6 @@ test_al No module named al
test_applesingle Not really a failure, but it tries to skip itself and we don't support that test_applesingle Not really a failure, but it tries to skip itself and we don't support that
test_argparse [unknown] test_argparse [unknown]
test_ascii_formatd segfault in ctypes (but only on CI) test_ascii_formatd segfault in ctypes (but only on CI)
test_asynchat [unknown]
test_asyncore [unknown]
test_atexit [unknown] test_atexit [unknown]
test_audioop [unknown] test_audioop [unknown]
test_bigmem [unknown] test_bigmem [unknown]
...@@ -96,7 +94,6 @@ test_file_eintr not sure ...@@ -96,7 +94,6 @@ test_file_eintr not sure
test_fileio [unknown] test_fileio [unknown]
test_fork1 [unknown] test_fork1 [unknown]
test_frozen [unknown] test_frozen [unknown]
test_ftplib [unknown]
test_funcattrs we don't allow changing numing of function defaults test_funcattrs we don't allow changing numing of function defaults
test_functools unknown errors test_functools unknown errors
test_future5 [unknown] test_future5 [unknown]
...@@ -112,7 +109,6 @@ test_gl [unknown] ...@@ -112,7 +109,6 @@ test_gl [unknown]
test_grammar bug in our tokenizer test_grammar bug in our tokenizer
test_heapq [unknown] test_heapq [unknown]
test_hotshot [unknown] test_hotshot [unknown]
test_httplib [unknown]
test_httpservers [unknown] test_httpservers [unknown]
test_idle [unknown] test_idle [unknown]
test_imageop [unknown] test_imageop [unknown]
...@@ -155,7 +151,6 @@ test_pep352 various unique bugs ...@@ -155,7 +151,6 @@ test_pep352 various unique bugs
test_pickletools [unknown] test_pickletools [unknown]
test_pickle unknown test_pickle unknown
test_pkg unknown bug test_pkg unknown bug
test_poplib SSLError (but only on CI)
test_pprint [unknown] test_pprint [unknown]
test_profile [unknown] test_profile [unknown]
test_py3kwarn [unknown] test_py3kwarn [unknown]
...@@ -173,11 +168,10 @@ test_scope eval of code object from existing function (not currentl ...@@ -173,11 +168,10 @@ test_scope eval of code object from existing function (not currentl
test_scriptpackages [unknown] test_scriptpackages [unknown]
test_shelve [unknown] test_shelve [unknown]
test_site [unknown] test_site [unknown]
test_socketserver [unknown] test_socketserver missing imp.lock_held, otherwise works
test_socket [unknown] test_socket [unknown]
test_sort argument specification issue in listSort? test_sort argument specification issue in listSort?
test_sqlite [unknown] test_sqlite [unknown]
test_ssl [unknown]
test_startfile [unknown] test_startfile [unknown]
test_str memory leak? test_str memory leak?
test_structmembers [unknown] test_structmembers [unknown]
...@@ -194,7 +188,6 @@ test_sys_settrace [unknown] ...@@ -194,7 +188,6 @@ test_sys_settrace [unknown]
test_sys [unknown] test_sys [unknown]
test_tarfile [unknown] test_tarfile [unknown]
test_tcl [unknown] test_tcl [unknown]
test_telnetlib [unknown]
test_tempfile [unknown] test_tempfile [unknown]
test_threaded_import [unknown] test_threaded_import [unknown]
test_threading_local [unknown] test_threading_local [unknown]
...@@ -217,8 +210,6 @@ test_unicode_file exit code 139, no error message ...@@ -217,8 +210,6 @@ test_unicode_file exit code 139, no error message
test_unittest serialize_ast assert test_unittest serialize_ast assert
test_univnewlines2k [unknown] test_univnewlines2k [unknown]
test_univnewlines [unknown] test_univnewlines [unknown]
test_urllib2net [unknown]
test_urllibnet [unknown]
test_userdict segfault: repr of recursive dict? test_userdict segfault: repr of recursive dict?
test_userlist slice(1L, 1L) test_userlist slice(1L, 1L)
test_userstring float(1L); hangs in test_replace test_userstring float(1L); hangs in test_replace
......
../../from_cpython/Lib/test/badcert.pem
\ No newline at end of file
../../from_cpython/Lib/test/badkey.pem
\ No newline at end of file
../../from_cpython/Lib/test/https_svn_python_org_root.pem
\ No newline at end of file
../../from_cpython/Lib/test/keycert.pem
\ No newline at end of file
../../from_cpython/Lib/test/nokia.pem
\ No newline at end of file
../../from_cpython/Lib/test/nullbytecert.pem
\ No newline at end of file
../../from_cpython/Lib/test/nullcert.pem
\ No newline at end of file
../../from_cpython/Lib/test/sha256.pem
\ No newline at end of file
../../from_cpython/Lib/test/wrongcert.pem
\ No newline at end of file
...@@ -20,4 +20,18 @@ diff -ur M2Crypto-0.21.1.orig/SWIG/_lib.i ./SWIG/_lib.i ...@@ -20,4 +20,18 @@ diff -ur M2Crypto-0.21.1.orig/SWIG/_lib.i ./SWIG/_lib.i
new_style_callback = 1; new_style_callback = 1;
} }
} else { } else {
diff -ur M2Crypto-0.21.1/M2Crypto/m2urllib2.py ./M2Crypto/m2urllib2.py
--- M2Crypto-0.21.1/M2Crypto/m2urllib2.py 2011-01-15 19:10:05.000000000 +0000
+++ ./M2Crypto/m2urllib2.py 2016-02-10 14:36:12.091812337 +0000
@@ -97,6 +97,11 @@
# out of socket._fileobject() and into a base class.
r.recv = r.read
+
+ # Pyston change: our socket implementation needs this functions
+ r._reuse = lambda: None
+ r._drop = lambda: None
+
fp = _closing_fileobject(r)
resp = addinfourl(fp, r.msg, req.get_full_url())
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment