OpenSSL 暗号化ライブラリを多用するマルチスレッド アプリケーションを実装しています。
ここのいくつかの投稿 ( pthreads、OpenSSL、およびマルチスレッドでの OpenSSL の使用に関するチュートリアル)、Web サイト (例: libcurl opensslthreadlock.c )、および主に OpenSSL に含まれるcrypto/threads/mttest.cプログラムのサンプル コードのガイドラインに従いました。ソースコード。そこで参照されている例は、主に OpenSSL の静的ロック コールバック関数を扱っています。しかし、この問題に関する OpenSSL のドキュメント ( OpenSSL: threads(3) ) およびThe Definitive Guide to Linux Network Programming (pages 255-259) によると、動的ロック管理のためにいくつかの関数を定義する必要がある場合があります。
したがって、両方のタイプのロック管理関数 (静的および動的) を設定する初期化関数とクリーンアップ関数を実装しました。これらの機能は次のとおりです。
static unsigned long _thread_id_function(void) {
return ((unsigned long) pthread_self());
}
static void _locking_function(int mode, int id, const char *file, int line) {
if(mode & CRYPTO_LOCK) {
pthread_mutex_lock(&mutex_buffer[id]);
} else {
pthread_mutex_unlock(&mutex_buffer[id]);
}
}
static struct CRYPTO_dynlock_value* _dyn_create_func(const char *file, int line) {
struct CRYPTO_dynlock_value *value;
value = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
pthread_mutex_init(&value->mutex,NULL);
return value;
}
static void _dyn_destroy_func(struct CRYPTO_dynlock_value *l,
const char *file, int line) {
pthread_mutex_destroy(&l->mutex);
free(l);
return;
}
static void _dyn_lock_func(int mode, struct CRYPTO_dynlock_value *l,
const char *file, int line) {
if(mode & CRYPTO_LOCK) {
pthread_mutex_lock(&l->mutex);
} else {
pthread_mutex_unlock(&l->mutex);
}
}
static int _static_init() {
int i;
mutex_buffer = (pthread_mutex_t *) malloc(CRYPTO_num_locks()*sizeof(pthread_mutex_t));
for(i=0; i<CRYPTO_num_locks(); i++) {
pthread_mutex_init(&mutex_buffer[i], NULL);
}
CRYPTO_set_id_callback(_thread_id_function);
CRYPTO_set_locking_callback(_locking_function);
return 0;
}
static int _static_cleanup() {
int i;
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
for(i=0; i<CRYPTO_num_locks(); i++) {
pthread_mutex_destroy(&mutex_buffer[i]);
}
free(mutex_buffer); mutex_buffer = NULL;
return 0;
}
static int _dyn_init() {
CRYPTO_set_dynlock_create_callback(_dyn_create_func);
CRYPTO_set_dynlock_lock_callback(_dyn_lock_func);
CRYPTO_set_dynlock_destroy_callback(_dyn_destroy_func);
return 0;
}
static int _dyn_cleanup() {
CRYPTO_set_dynlock_create_callback(NULL);
CRYPTO_set_dynlock_lock_callback(NULL);
CRYPTO_set_dynlock_destroy_callback(NULL);
return 0;
}
int cryptothread_init() {
_static_init();
_dyn_init();
return 0;
}
int cryptothread_cleanup() {
_static_cleanup();
_dyn_cleanup();
return 0;
}
メイン プログラムからcryptothread_init関数を呼び出して、コールバックを初期化します。ただし、Valgrind の Helgrind ツールを実行すると、いくつかの競合状態が発生します。
==18797== スレッド #3 による 0x75D2F28 でのサイズ 4 の書き込み中にデータ競合が発生する可能性があります
==18797== 保持されているロック: なし
==18797== 0x7276DCA: CRYPTO_malloc (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72F6290: EVP_MD_CTX_copy_ex (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72FD57B: EVP_SignFinal (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x407007: sign_data (main.c:919)
==18797== by 0x4C2B5AD: ??? (/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so 内)
==18797== by 0x5CACB4F: start_thread (pthread_create.c:304)
==18797== by 0x6F4EA7C: クローン (clone.S:112)
==18797==
==18797== これは、スレッド #4 によるサイズ 4 の以前の書き込みと競合します
==18797== 保持されているロック: なし
==18797== 0x7276DCA: CRYPTO_malloc (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72B0086: ??? (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72B05AC: bn_expand2 (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72B08C9: BN_set_word (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72B1317: BN_CTX_get (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72AD68A: BN_div (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72D1841: ??? (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797== by 0x72D2B9A: ??? (/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 内)
==18797==
それでも、ロック コールバックはエラー/警告メッセージをスローしません。何が欠けているかについてのヒントはありますか?