Initialize OpenSSL for use with threads.
This is totally necessary in order to use OpenSSL APIs from more than one thread without
memory corruption.
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index a4adacf..d4fc882 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -694,6 +694,73 @@
{ NULL, NULL }
};
+
+#ifdef WITH_THREAD
+
+#include <pythread.h>
+
+/**
+ * This array will store all of the mutexes available to OpenSSL.
+ */
+static PyThread_type_lock *mutex_buf = NULL;
+
+
+/**
+ * Callback function supplied to OpenSSL to acquire or release a lock.
+ *
+ */
+static void locking_function(int mode, int n, const char * file, int line) {
+ if (mode & CRYPTO_LOCK) {
+ PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
+ } else {
+ PyThread_release_lock(mutex_buf[n]);
+ }
+}
+
+
+/**
+ * Initialize OpenSSL for use from multiple threads.
+ *
+ * Returns: 0 if initialization fails, 1 otherwise.
+ */
+static int init_openssl_threads(void) {
+ int i;
+
+ mutex_buf = (PyThread_type_lock *)malloc(
+ CRYPTO_num_locks() * sizeof(PyThread_type_lock));
+ if (!mutex_buf) {
+ return 0;
+ }
+ for (i = 0; i < CRYPTO_num_locks(); ++i) {
+ mutex_buf[i] = PyThread_allocate_lock();
+ }
+ CRYPTO_set_id_callback(PyThread_get_thread_ident);
+ CRYPTO_set_locking_callback(locking_function);
+ return 1;
+}
+
+/* /\** */
+/* * Clean up after OpenSSL thread initialization. */
+/* *\/ */
+/* static int deinit_openssl_threads() { */
+/* int i; */
+
+/* if (!mutex_buf) { */
+/* return 0; */
+/* } */
+/* CRYPTO_set_id_callback(NULL); */
+/* CRYPTO_set_locking_callback(NULL); */
+/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
+/* PyThread_free_lock(mutex_buf[i]); */
+/* } */
+/* free(mutex_buf); */
+/* mutex_buf = NULL; */
+/* return 1; */
+/* } */
+
+#endif
+
+
/*
* Initialize crypto sub module
*
@@ -739,6 +806,10 @@
PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
dict = PyModule_GetDict(module);
+#ifdef WITH_THREAD
+ if (!init_openssl_threads())
+ goto error;
+#endif
if (!init_crypto_x509(dict))
goto error;
if (!init_crypto_x509name(dict))