Commits

Armin Rigo  committed d8f7490

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)

  • Participants
  • Parent commits c778cc8
  • Branches release-1.6.x

Comments (0)

Files changed (3)

File pypy/module/_ssl/interp_ssl.py

         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:

File pypy/module/_ssl/test/test_ssl.py

         _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()
             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:
             """)
 
     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")
         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

File pypy/rlib/ropenssl.py

 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)
 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)
 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)