Last active
January 1, 2016 10:39
-
-
Save public/8132604 to your computer and use it in GitHub Desktop.
Implement the OpenSSL locking callback in Python. It seems to work but is ~4x slower on PyPy and ~8x slower in CPython than using the C implementation from Modules/_ssl.py.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import thread | |
import threading | |
import itertools | |
import cryptography.hazmat.backends | |
b = cryptography.hazmat.backends.default_backend() | |
# UNCOMMENT THIS TO POSSIBLY STOP CRASHES | |
#import _ssl | |
# OR | |
# ENABLE THIS BLOCK TO HANDLE THE LOCKING IN PYTHON | |
""" | |
You need this patch to crypto.py for this | |
index 8d88c16..293e361 100644 | |
--- a/cryptography/hazmat/backends/openssl/crypto.py | |
+++ b/cryptography/hazmat/backends/openssl/crypto.py | |
@@ -24,6 +24,8 @@ int CRYPTO_mem_ctrl(int); | |
int CRYPTO_is_mem_check_on(); | |
void CRYPTO_mem_leaks(struct bio_st *); | |
void CRYPTO_cleanup_all_ex_data(); | |
+void CRYPTO_set_locking_callback(void (*func)(int, int, const char *, int)); | |
+int CRYPTO_num_locks(); | |
void OPENSSL_free(void *); | |
\"\"\" | |
""" | |
if 1: | |
import thread | |
_ssl_locks_count = b.lib.CRYPTO_num_locks() | |
_ssl_locks = [thread.allocate_lock() | |
for n in range(_ssl_locks_count)] | |
CRYPTO_LOCK = 1 | |
def ssl_lock(mode, n, file, line): | |
global _ssl_locks | |
assert _ssl_locks | |
assert n >= 0 | |
assert n < _ssl_locks_count | |
lock = _ssl_locks[n] | |
if mode & CRYPTO_LOCK: | |
lock.acquire(1) | |
else: | |
lock.release() | |
ssl_lock_cb = b.ffi.callback( | |
"void(int mode, int n, const char *file, int line)", | |
ssl_lock | |
) | |
b.lib.CRYPTO_set_locking_callback(ssl_lock_cb) | |
def randloop(): | |
s = b.ffi.new("char[]", 16) | |
sb = b.ffi.buffer(s) | |
sb[:] = b"\0" * 16 | |
for i in itertools.count(): | |
b.lib.RAND_seed(s, 16) | |
if i % 10000 == 0: | |
print thread.get_ident(), i | |
if i > 300000: | |
break | |
threads = [] | |
print "Starting..." | |
for x in range(3): | |
t = threading.Thread(target=randloop) | |
t.daemon = True | |
t.start() | |
threads.append(t) | |
print "Waiting..." | |
while threads: | |
for t in threads: | |
t.join(0.1) | |
if not t.isAlive(): | |
threads.remove(t) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment