changeset 2166:8a01e8f21de9

Make OpenSSL usage thread-safe (closes #206) Enable OpenSSL?s multithreading support by defining locking and thread-ID callbacks. Remove a lock obviated by this change.
author Benjamin Barenblat <bbaren@mit.edu>
date Thu, 06 Aug 2015 10:15:53 -0400
parents 7dfce558aca2
children a9dc205edd78
files src/c/openssl.c src/c/urweb.c
diffstat 2 files changed, 40 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/c/openssl.c	Thu Aug 06 09:57:47 2015 -0400
+++ b/src/c/openssl.c	Thu Aug 06 10:15:53 2015 -0400
@@ -1,5 +1,6 @@
 #include "config.h"
 
+#include <assert.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -7,12 +8,17 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
+#include <pthread.h>
 
+#include <openssl/crypto.h>
 #include <openssl/sha.h>
 #include <openssl/rand.h>
 
 #define PASSSIZE 4
 
+// OpenSSL locks array.  See threads(3SSL).
+static pthread_mutex_t *openssl_locks;
+
 int uw_hash_blocksize = 32;
 
 static int password[PASSSIZE];
@@ -27,7 +33,41 @@
   }
 }
 
+// OpenSSL callbacks
+static void thread_id(CRYPTO_THREADID *const result) {
+  CRYPTO_THREADID_set_numeric(result, pthread_self());
+}
+static void lock_or_unlock(const int mode, const int type, const char *file,
+                           const int line) {
+  pthread_mutex_t *const lock = &openssl_locks[type];
+  if (mode & CRYPTO_LOCK) {
+    if (pthread_mutex_lock(lock)) {
+      fprintf(stderr, "Can't take lock at %s:%d\n", file, line);
+      exit(1);
+    }
+  } else {
+    if (pthread_mutex_unlock(lock)) {
+      fprintf(stderr, "Can't release lock at %s:%d\n", file, line);
+      exit(1);
+    }
+  }
+}
+
 void uw_init_crypto() {
+  int i;
+  // Set up OpenSSL.
+  assert(openssl_locks == NULL);
+  openssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
+  if (!openssl_locks) {
+    perror("malloc");
+    exit(1);
+  }
+  for (i = 0; i < CRYPTO_num_locks(); ++i) {
+    pthread_mutex_init(&(openssl_locks[i]), NULL);
+  }
+  CRYPTO_THREADID_set_callback(thread_id);
+  CRYPTO_set_locking_callback(lock_or_unlock);
+  // Prepare signatures.
   if (uw_sig_file) {
     int fd;
 
--- a/src/c/urweb.c	Thu Aug 06 09:57:47 2015 -0400
+++ b/src/c/urweb.c	Thu Aug 06 10:15:53 2015 -0400
@@ -167,13 +167,8 @@
 void uw_free_client_data(void *);
 void uw_copy_client_data(void *dst, void *src);
 
-static pthread_mutex_t rand_mutex = PTHREAD_MUTEX_INITIALIZER;
-
 static uw_Basis_int my_rand() {
-  pthread_mutex_lock(&rand_mutex);
   int ret, r = RAND_bytes((unsigned char *)&ret, sizeof ret);
-  pthread_mutex_unlock(&rand_mutex);
-
   if (r)
     return abs(ret);
   else