Subject: | [PATCH} ithreads support |
Using perl ithreads, we can set up multiple LWP::UserAgents to fetch
many pages simultaneously. However, when more than two threads are
accessing https:// URLs, perl occasionally reports corrupted memory and
dies.
This is because Crypt::SSLeay lacks mutex setup that is required by
OpenSSL library.
The attached patch is a trial to fix this problem. The patch is for
Crypt::SSLeay 0.57_01.
Unfortunately the patch is pthread-specific, so more work is necessary
to support other thread libraries. I tested the patch on Linux 2.6
(Debian etch) and it seems working.
Some code in the patch is copied from
http://www.nabble.com/When-to-use-CRYPTO_set_locking_callback()-and-
CRYPTO_set_id_callback()--td5849882.html
I hope (more complete) thread support is included in the future version
of Crypt::SSLeay.
Subject: | crypt.diff |
diff -r -c Crypt-SSLeay-0.57_01/META.yml Crypt-SSLeay-0.57_01+ithreads/META.yml
*** Crypt-SSLeay-0.57_01/META.yml 2008-02-18 23:43:14.000000000 +0900
--- Crypt-SSLeay-0.57_01+ithreads/META.yml 2008-11-13 09:53:09.000000000 +0900
***************
*** 1,6 ****
--- #YAML:1.0
name: Crypt-SSLeay
! version: 0.57_01
abstract: OpenSSL support for LWP
license: perl
author:
--- 1,6 ----
--- #YAML:1.0
name: Crypt-SSLeay
! version: 0.57_01+ithreads
abstract: OpenSSL support for LWP
license: perl
author:
diff -r -c Crypt-SSLeay-0.57_01/SSLeay.pm Crypt-SSLeay-0.57_01+ithreads/SSLeay.pm
*** Crypt-SSLeay-0.57_01/SSLeay.pm 2008-02-18 23:33:14.000000000 +0900
--- Crypt-SSLeay-0.57_01+ithreads/SSLeay.pm 2008-11-13 09:51:28.000000000 +0900
***************
*** 2,8 ****
use strict;
use vars '$VERSION';
! $VERSION = '0.57_01';
eval {
require XSLoader;
--- 2,8 ----
use strict;
use vars '$VERSION';
! $VERSION = '0.57_01+ithreads';
eval {
require XSLoader;
diff -r -c Crypt-SSLeay-0.57_01/SSLeay.xs Crypt-SSLeay-0.57_01+ithreads/SSLeay.xs
*** Crypt-SSLeay-0.57_01/SSLeay.xs 2008-02-18 23:11:15.000000000 +0900
--- Crypt-SSLeay-0.57_01+ithreads/SSLeay.xs 2008-11-13 11:37:55.000000000 +0900
***************
*** 18,23 ****
--- 18,24 ----
#define PERL5 1
#endif
+ #define OPENSSL_THREAD_DEFINES
/* ssl.h or openssl/ssl.h is included from the crypt_ssleay_version
* file which is written when building with perl Makefile.PL
* #include "ssl.h"
***************
*** 25,34 ****
--- 26,73 ----
#include "crypt_ssleay_version.h"
#undef Free /* undo namespace pollution from crypto.h */
+
+ #if defined(OPENSSL_THREADS)
+ #include <pthread.h>
+ #endif
#ifdef __cplusplus
}
#endif
+ #if defined(OPENSSL_THREADS)
+ static pthread_mutex_t *mutex_buf = NULL;
+ static int mutex_use = 0;
+ static int mutex_free = 0;
+ static pthread_mutex_t mutex_lib;
+
+ /**
+ * OpenSSL locking function.
+ *
+ * @param mode lock mode
+ * @param n lock number
+ * @param file source file name
+ * @param line source file line number
+ * @return none
+ */
+ static void locking_function(int mode, int n, const char *file, int line)
+ {
+ if (mode & CRYPTO_LOCK) {
+ pthread_mutex_lock(&mutex_buf[n]);
+ } else {
+ pthread_mutex_unlock(&mutex_buf[n]);
+ }
+ }
+
+ /**
+ * OpenSSL uniq id function.
+ *
+ * @return thread id
+ */
+ static unsigned long id_function(void)
+ {
+ return ((unsigned long) pthread_self());
+ }
+ #endif // OPENSSL_THREADS
/* moved this out to Makefile.PL so user can
* see value being used printed during build
***************
*** 103,109 ****
--- 142,171 ----
static int bNotFirstTime;
char buf[1024];
int rand_bytes_read;
+ int i;
+ #if defined(OPENSSL_THREADS)
+ if( mutex_use == 0 )
+ {
+ mutex_use++;
+ pthread_mutex_init( &mutex_lib, NULL );
+ pthread_mutex_lock( &mutex_lib );
+ /* static locks area */
+ mutex_buf = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
+ //if (mutex_buf == NULL) {
+ // return (-1);
+ //}
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ pthread_mutex_init(&mutex_buf[i], NULL);
+ }
+ /* static locks callbacks */
+ CRYPTO_set_locking_callback(locking_function);
+ CRYPTO_set_id_callback(id_function);
+ } else {
+ pthread_mutex_lock(&mutex_lib);
+ mutex_use++;
+ }
+ #endif // OPENSSL_THREADS
if(!bNotFirstTime) {
SSLeay_add_all_algorithms();
SSL_load_error_strings();
***************
*** 136,147 ****
--- 198,214 ----
SSL_CTX_set_default_verify_paths(ctx);
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
RETVAL = ctx;
+ #if defined(OPENSSL_THREADS)
+ pthread_mutex_unlock(&mutex_lib);
+ #endif
OUTPUT:
RETVAL
void
SSL_CTX_free(ctx)
SSL_CTX* ctx
+ CODE:
+ mutex_free++;
int
SSL_CTX_set_cipher_list(ctx, ciphers)