2

我正在实现一个广泛使用 OpenSSL 加密库的多线程应用程序。

我在这里的几篇文章中遵循了指南(关于使用 OpenSSL 与 pthreadsOpenSSL 和多线程的教程)、网站(例如libcurl opensslthreadlock.c ),主要是 OpenSSL 中包含的crypto/threads/mttest.c程序中的示例代码源代码。其中引用的示例主要处理 OpenSSL 的静态锁回调函数。但是,同样根据有关此事的 OpenSSL 文档(OpenSSL:threads(3))和Linux 网络编程权威指南(第 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== 0x72F6290:EVP_MD_CTX_copy_ex(在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797== 0x72FD57B:EVP_SignFinal(在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797== 0x407007:sign_data (main.c:919)

==18797== 由 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== 由 0x72B0086: ??? (在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797== 由 0x72B05AC:bn_expand2(在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797== 由 0x72B08C9:BN_set_word(在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797== 0x72B1317:BN_CTX_get(在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797== 由 0x72AD68A:BN_div(在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797== 由 0x72D1841: ??? (在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797== 由 0x72D2B9A: ??? (在 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 中)

==18797==

尽管如此,锁定回调不会抛出任何错误/警告消息。关于我可能缺少什么的任何提示?

4

0 回答 0