Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add thread safety to OpenSSL gem

With OpenSSL, you need to register some methods to make sure OpenSSL is
thread safe to use. Since we don't want to lock around the whole
extension, we make sure to setup this stuff.
  • Loading branch information...
commit 677aac929b7c97151534649c91a678df2869736b 1 parent fa98fa8
@dbussink dbussink authored
View
37 lib/18/openssl/ext/ossl.c
@@ -406,6 +406,37 @@ ossl_debug_set(VALUE self, VALUE val)
return val;
}
+/**
+ * Stores locks needed for OpenSSL thread safety
+ */
+static VALUE* ossl_locks;
+
+static void ossl_lock_callback(int mode, int type, char *file, int line)
+{
+ if (mode & CRYPTO_LOCK) {
+ rb_mutex_lock(ossl_locks[type]);
+ } else {
+ rb_mutex_unlock(ossl_locks[type]);
+ }
+}
+
+static unsigned long ossl_thread_id(void)
+{
+ return NUM2ULONG(rb_obj_id(rb_thread_current()));
+}
+
+static void Init_ossl_locks(void)
+{
+ ossl_locks = (VALUE*) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(VALUE));
+ for (int i = 0; i < CRYPTO_num_locks(); i++) {
+ ossl_locks[i] = rb_mutex_new();
+ rb_global_variable(&(ossl_locks[i]));
+ }
+
+ CRYPTO_set_id_callback((unsigned long (*)())ossl_thread_id);
+ CRYPTO_set_locking_callback((void (*)())ossl_lock_callback);
+}
+
/*
* OSSL library init
*/
@@ -447,6 +478,7 @@ Init_openssl()
* Init main module
*/
mOSSL = rb_define_module("OpenSSL");
+ rb_global_variable(&mOSSL);
/*
* Constants
@@ -460,6 +492,7 @@ Init_openssl()
* common for all classes under OpenSSL module
*/
eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
+ rb_global_variable(&eOSSLError);
/*
* Verify callback Proc index for ext-data
@@ -471,6 +504,8 @@ Init_openssl()
* Init debug core
*/
dOSSL = Qfalse;
+ rb_global_variable(&dOSSL);
+
rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
@@ -480,6 +515,8 @@ Init_openssl()
*/
ossl_s_to_der = rb_intern("to_der");
+ Init_ossl_locks();
+
/*
* Init components
*/
View
37 lib/19/openssl/ext/ossl.c
@@ -415,6 +415,37 @@ ossl_debug_set(VALUE self, VALUE val)
return val;
}
+/**
+ * Stores locks needed for OpenSSL thread safety
+ */
+static VALUE* ossl_locks;
+
+static void ossl_lock_callback(int mode, int type, char *file, int line)
+{
+ if (mode & CRYPTO_LOCK) {
+ rb_mutex_lock(ossl_locks[type]);
+ } else {
+ rb_mutex_unlock(ossl_locks[type]);
+ }
+}
+
+static unsigned long ossl_thread_id(void)
+{
+ return NUM2ULONG(rb_obj_id(rb_thread_current()));
+}
+
+static void Init_ossl_locks(void)
+{
+ ossl_locks = (VALUE*) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(VALUE));
+ for (int i = 0; i < CRYPTO_num_locks(); i++) {
+ ossl_locks[i] = rb_mutex_new();
+ rb_global_variable(&(ossl_locks[i]));
+ }
+
+ CRYPTO_set_id_callback((unsigned long (*)())ossl_thread_id);
+ CRYPTO_set_locking_callback((void (*)())ossl_lock_callback);
+}
+
/*
* OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
* OpenSSL[http://www.openssl.org/] library.
@@ -826,6 +857,7 @@ Init_openssl()
* Init main module
*/
mOSSL = rb_define_module("OpenSSL");
+ rb_global_variable(&mOSSL);
/*
* OpenSSL ruby extension version
@@ -847,6 +879,7 @@ Init_openssl()
* common for all classes under OpenSSL module
*/
eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
+ rb_global_variable(&eOSSLError);
/*
* Verify callback Proc index for ext-data
@@ -858,6 +891,8 @@ Init_openssl()
* Init debug core
*/
dOSSL = Qfalse;
+ rb_global_variable(&dOSSL);
+
rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
@@ -867,6 +902,8 @@ Init_openssl()
*/
ossl_s_to_der = rb_intern("to_der");
+ Init_ossl_locks();
+
/*
* Init components
*/
View
37 lib/20/openssl/ext/ossl.c
@@ -415,6 +415,37 @@ ossl_debug_set(VALUE self, VALUE val)
return val;
}
+/**
+ * Stores locks needed for OpenSSL thread safety
+ */
+static VALUE* ossl_locks;
+
+static void ossl_lock_callback(int mode, int type, char *file, int line)
+{
+ if (mode & CRYPTO_LOCK) {
+ rb_mutex_lock(ossl_locks[type]);
+ } else {
+ rb_mutex_unlock(ossl_locks[type]);
+ }
+}
+
+static unsigned long ossl_thread_id(void)
+{
+ return NUM2ULONG(rb_obj_id(rb_thread_current()));
+}
+
+static void Init_ossl_locks(void)
+{
+ ossl_locks = (VALUE*) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(VALUE));
+ for (int i = 0; i < CRYPTO_num_locks(); i++) {
+ ossl_locks[i] = rb_mutex_new();
+ rb_global_variable(&(ossl_locks[i]));
+ }
+
+ CRYPTO_set_id_callback((unsigned long (*)())ossl_thread_id);
+ CRYPTO_set_locking_callback((void (*)())ossl_lock_callback);
+}
+
/*
* OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
* OpenSSL[http://www.openssl.org/] library.
@@ -826,6 +857,7 @@ Init_openssl()
* Init main module
*/
mOSSL = rb_define_module("OpenSSL");
+ rb_global_variable(&mOSSL);
/*
* OpenSSL ruby extension version
@@ -847,6 +879,7 @@ Init_openssl()
* common for all classes under OpenSSL module
*/
eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
+ rb_global_variable(&eOSSLError);
/*
* Verify callback Proc index for ext-data
@@ -858,6 +891,8 @@ Init_openssl()
* Init debug core
*/
dOSSL = Qfalse;
+ rb_global_variable(&dOSSL);
+
rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);
@@ -867,6 +902,8 @@ Init_openssl()
*/
ossl_s_to_der = rb_intern("to_der");
+ Init_ossl_locks();
+
/*
* Init components
*/
Please sign in to comment.
Something went wrong with that request. Please try again.