c - 使用 OpenMP 和 OpenSSL 时的内存泄漏和段错误

标签 c multithreading openssl openmp

我有一个巨大的代码(这是我的学校项目),我在其中使用 Openssl。一切都很完美,直到我决定采用多线程。我选择 openmp 作为我的线程环境,因为它非常简单且易于学习(至少我需要的基础很简单)。

我的整个代码如下所示:

struct mystr[10];
omp_set_num_threads(10);
#pragma omp parallel 
{
    mystr[omp_get_thread_num()] = call_fun_which_uses_openssl();
}
CRYPTO_cleanup_all_ex_data();

我的 call_fun_which_uses_openssl 函数使用低级 openssls api 函数 (MD4((unsigned char*)&string, strlen(string), (unsigned char*)&digest); MD4_CTX ctx 等)。我的函数使用 RSA、DSA...并且无法访问任何全局变量,它使用的每个变量都在 call_fun_which_uses_openssl 内声明,因此像我一样执行多线程应该保证这些变量保持私有(private)。虽然,我有时会遇到这段代码的段错误。我读到 CRYPTO_cleanup_all_ex_data 不是线程安全的(但由于内存泄漏我需要它),但我在并行区域之外使用它,对吧?当我删除 openmp 调用时,每次都会正常工作,因此多线程和 openssl 一定存在问题。有什么想法如何解决吗?

在我看来它应该可以工作,因为 call_fun_which_uses_openssl 的线程调用为每个线程创建自己的私有(private)变量,应该没有问题......请帮助:)

最佳答案

查看 OpenSSL 源代码树中的示例 openssl/crypto/threads/mttest.c。基本上,您必须提供两个回调函数:

  • 实现锁定和解锁的一个
  • 返回唯一的线程 ID。

两者都可以使用 OpenMP 轻松实现:

omp_lock_t *locks;

// Locking callback
void openmp_locking_callback(int mode, int type, char *file, int line)
{
  if (mode & CRYPTO_LOCK)
  {
    omp_set_lock(&locks[type]);
  }
  else
  {
    omp_unset_lock(&locks[type]);
  }
}

// Thread ID callback
unsigned long openmp_thread_id(void)
{
  return (unsigned long)omp_get_thread_num();
}

开始之前,必须初始化锁并设置回调:

void openmp_thread_setup(void)
{
  int i;

  locks = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(omp_lock_t));
  for (i=0; i<CRYPTO_num_locks(); i++)
  {
    omp_init_lock(&locks[i]);
  }

  CRYPTO_set_id_callback((unsigned long (*)())openmp_thread_id);
  CRYPTO_set_locking_callback((void (*)())openmp_locking_callback);
}

void openmp_thread_cleanup(void)
{
  int i;

  CRYPTO_set_id_callback(NULL);
  CRYPTO_set_locking_callback(NULL);
  for (i=0; i<CRYPTO_num_locks(); i++)
    omp_destroy_lock(&locks[i]);
  OPENSSL_free(locks);
}

您应该在程序中第一个并行区域之前的某个位置调用 openmp_thread_setup() 一次,并且应该在最后一个并行区域之后调用 openmp_thread_cleanup() 一次:

// Program start

openmp_thread_setup();

#pragma omp parallel
{
   // Parallel OpenSSL calls are now data race free
}

#pragma omp parallel
{
   // Parallel OpenSSL calls are now data race free
}

#pragma omp parallel
{
   // Parallel OpenSSL calls are now data race free
}

openmp_thread_cleanup();

// Program should end now

关于c - 使用 OpenMP 和 OpenSSL 时的内存泄漏和段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22906207/

相关文章:

memset 可以在 4 核上并行化吗?

c++ - 竞争条件 : One thread creates static object, 另一个线程在完成初始化之前使用它。如何处理?

c - 暂时转义函数范围以在 C 中定义全局符号? (海湾合作委员会)

c - 从 NETSTAT 的输出中删除

c - 用于百分比计算、掷骰子程序的 Nan 输出

C# 窗口在忙碌时变得空白 -> 进度条?但是怎么办?

visual-studio-2015 - 使用openssl时如何检测内存泄漏

c++ - tcp_connect 中的 gSoap SSL/TLS 证书主机名不匹配

ssl - OpenSSL 创建 pfx 证书

c - 编写 C 编译器时应该如何解析关键字?