我正在实现一个多线程应用程序,它广泛使用OpenSSL加密库。
我已在此处的几个帖子(Tutorial on Using OpenSSL with pthreads,OpenSSL and multi-threads),网站(例如libcurl opensslthreadlock.c)中遵循指南,主要是加密/ threads / mttest中的示例代码OpenSSL源代码中包含的.c 程序。其中引用的示例主要涉及OpenSSL的静态锁回调函数。但是,根据OpenSSL关于此事的文档(OpenSSL: threads(3))和The Definitive Guide to Linux Network Programming (第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(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 ==
但是,锁定回调不会抛出任何错误/警告消息。关于我可能遗失的任何暗示?
答案 0 :(得分:0)
你应该完全阅读。 openSSL提供了两种设置回调以进行锁定的可能性。
所谓的“静态”和“动态”方式。您正在配置两者。我使用老式的静态,没有问题。我认为只有你应该使用动态的东西:减少用过的内存。但这对于使用过的记忆来说是荒谬的。
最后,您可以在“注释”部分的线程(3).html中看到静音的动态方式未启用。