[pypy-commit] pypy release-1.6.x: Can't call these ropenssl methods without releasing
arigo
noreply at buildbot.pypy.org
Mon Aug 15 11:40:19 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: release-1.6.x
Changeset: r46517:d8f74903d412
Date: 2011-08-15 10:52 +0200
http://bitbucket.org/pypy/pypy/changeset/d8f74903d412/
Log: Can't call these ropenssl methods without releasing the GIL. They
may call back RPython code that needs to acquire some locks!
Baaaaah**42. Instead make sure not to call them from a __del__,
with some enqueue_for_destruction(). (transplanted from
ab978bd157c94b51409d330a400b854127e86692)
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -138,6 +138,10 @@
return self.space.wrap(rffi.charp2str(self._issuer))
def __del__(self):
+ self.enqueue_for_destruction(self.space, SSLObject.destructor,
+ '__del__() method of ')
+
+ def destructor(self):
if self.peer_cert:
libssl_X509_free(self.peer_cert)
if self.ssl:
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -63,7 +63,7 @@
_ssl.RAND_egd("entropy")
def test_sslwrap(self):
- import _ssl, _socket, sys
+ import _ssl, _socket, sys, gc
if sys.platform == 'darwin':
skip("hangs indefinitely on OSX (also on CPython)")
s = _socket.socket()
@@ -73,15 +73,19 @@
assert exc.value.errno == 2 # Cannot find file (=not a socket)
else:
assert exc.value.errno == 32 # Broken pipe
+ del exc, ss, s
+ gc.collect() # force the destructor() to be called now
def test_async_closed(self):
- import _ssl, _socket
+ import _ssl, _socket, gc
s = _socket.socket()
s.settimeout(3)
ss = _ssl.sslwrap(s, 0)
s.close()
exc = raises(_ssl.SSLError, ss.write, "data")
assert exc.value.strerror == "Underlying socket has been closed."
+ del exc, ss, s
+ gc.collect() # force the destructor() to be called now
class AppTestConnectedSSL:
@@ -104,42 +108,47 @@
""")
def test_connect(self):
- import socket
+ import socket, gc
ss = socket.ssl(self.s)
self.s.close()
+ del ss; gc.collect()
def test_server(self):
- import socket
+ import socket, gc
ss = socket.ssl(self.s)
assert isinstance(ss.server(), str)
self.s.close()
+ del ss; gc.collect()
def test_issuer(self):
- import socket
+ import socket, gc
ss = socket.ssl(self.s)
assert isinstance(ss.issuer(), str)
self.s.close()
+ del ss; gc.collect()
def test_write(self):
- import socket
+ import socket, gc
ss = socket.ssl(self.s)
raises(TypeError, ss.write, 123)
num_bytes = ss.write("hello\n")
assert isinstance(num_bytes, int)
assert num_bytes >= 0
self.s.close()
+ del ss; gc.collect()
def test_read(self):
- import socket
+ import socket, gc
ss = socket.ssl(self.s)
raises(TypeError, ss.read, "foo")
ss.write("hello\n")
data = ss.read()
assert isinstance(data, str)
self.s.close()
+ del ss; gc.collect()
def test_read_upto(self):
- import socket
+ import socket, gc
ss = socket.ssl(self.s)
raises(TypeError, ss.read, "foo")
ss.write("hello\n")
@@ -148,15 +157,17 @@
assert len(data) == 10
assert ss.pending() > 50 # many more bytes to read
self.s.close()
+ del ss; gc.collect()
def test_shutdown(self):
- import socket, ssl, sys
+ import socket, ssl, sys, gc
if sys.platform == 'darwin':
skip("get also on CPython: error: [Errno 0]")
ss = socket.ssl(self.s)
ss.write("hello\n")
assert ss.shutdown() is self.s._sock
raises(ssl.SSLError, ss.write, "hello\n")
+ del ss; gc.collect()
class AppTestConnectedSSL_Timeout(AppTestConnectedSSL):
# Same tests, with a socket timeout
diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py
--- a/pypy/rlib/ropenssl.py
+++ b/pypy/rlib/ropenssl.py
@@ -197,7 +197,7 @@
ssl_external('X509_NAME_ENTRY_get_object', [X509_NAME_ENTRY], ASN1_OBJECT)
ssl_external('X509_NAME_ENTRY_get_data', [X509_NAME_ENTRY], ASN1_STRING)
ssl_external('i2d_X509', [X509, rffi.CCHARPP], rffi.INT)
-ssl_external('X509_free', [X509], lltype.Void, threadsafe=False)
+ssl_external('X509_free', [X509], lltype.Void)
ssl_external('X509_get_notBefore', [X509], ASN1_TIME, macro=True)
ssl_external('X509_get_notAfter', [X509], ASN1_TIME, macro=True)
ssl_external('X509_get_serialNumber', [X509], ASN1_INTEGER)
@@ -232,9 +232,9 @@
ssl_external('ERR_get_error', [], rffi.INT)
ssl_external('ERR_error_string', [rffi.ULONG, rffi.CCHARP], rffi.CCHARP)
-ssl_external('SSL_free', [SSL], lltype.Void, threadsafe=False)
-ssl_external('SSL_CTX_free', [SSL_CTX], lltype.Void, threadsafe=False)
-ssl_external('CRYPTO_free', [rffi.VOIDP], lltype.Void, threadsafe=False)
+ssl_external('SSL_free', [SSL], lltype.Void)
+ssl_external('SSL_CTX_free', [SSL_CTX], lltype.Void)
+ssl_external('CRYPTO_free', [rffi.VOIDP], lltype.Void)
libssl_OPENSSL_free = libssl_CRYPTO_free
ssl_external('SSL_write', [SSL, rffi.CCHARP, rffi.INT], rffi.INT)
@@ -246,7 +246,7 @@
ssl_external('BIO_s_file', [], BIO_METHOD)
ssl_external('BIO_new', [BIO_METHOD], BIO)
ssl_external('BIO_set_nbio', [BIO, rffi.INT], rffi.INT, macro=True)
-ssl_external('BIO_free', [BIO], rffi.INT, threadsafe=False)
+ssl_external('BIO_free', [BIO], rffi.INT)
ssl_external('BIO_reset', [BIO], rffi.INT, macro=True)
ssl_external('BIO_read_filename', [BIO, rffi.CCHARP], rffi.INT, macro=True)
ssl_external('BIO_gets', [BIO, rffi.CCHARP, rffi.INT], rffi.INT)
More information about the pypy-commit
mailing list