多线程程序使用OpenSSL和OpenMP进行段错误

时间:2018-01-19 16:06:43

标签: multithreading openssl segmentation-fault openmp

我在C中的多线程程序中使用OpenSSL并遇到问题。所以我写了一个小程序来试图缩小问题的范围。主要功能以外的功能是从https://github.com/plenluno/openssl/blob/master/openssl/crypto/threads/mttest.c

复制粘贴的

我的节目如下。

   #include<stdio.h>  
   #include<stdlib.h>
   #include<stdarg.h>
   #include <strings.h>
   #include <string.h>
   #include <math.h>
   #include <sys/stat.h>
   #include <fcntl.h>
   #include <unistd.h>
   #include<omp.h>
   #include <openssl/bn.h>
   #include <openssl/dh.h>
   #include <openssl/crypto.h>
   #include <pthread.h>
   #include <openssl/lhash.h>
   #include <openssl/buffer.h> 
   #include <openssl/x509.h>
   #include <openssl/ssl.h>
   #include <openssl/err.h>

   static pthread_mutex_t *lock_cs;
   static long *lock_count;

   void pthreads_locking_callback(int mode, int type, char *file,
     int line)
  {
   #if 0
      fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
      CRYPTO_thread_id(),
      (mode&CRYPTO_LOCK)?"l":"u",
      (type&CRYPTO_READ)?"r":"w",file,line);
   #endif
   #if 0
     if (CRYPTO_LOCK_SSL_CERT == type)
     fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
     CRYPTO_thread_id(),
     mode,file,line);
   #endif
   if (mode & CRYPTO_LOCK)
    {
    pthread_mutex_lock(&(lock_cs[type]));
    lock_count[type]++;
    }
    else
    {
    pthread_mutex_unlock(&(lock_cs[type]));
    }
   }

 unsigned long pthreads_thread_id(void)
 {
 unsigned long ret;

 ret=(unsigned long)pthread_self();
return(ret);
 }

void CRYPTO_thread_setup(void)
{
 int i;

 lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * 
  sizeof(pthread_mutex_t));
lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
for (i=0; i<CRYPTO_num_locks(); i++)
    {
    lock_count[i]=0;
    pthread_mutex_init(&(lock_cs[i]),NULL);
    }

CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
}

 void thread_cleanup(void)
 {
       int i;
       CRYPTO_set_locking_callback(NULL);
       for (i=0; i<CRYPTO_num_locks(); i++)
       {
           pthread_mutex_destroy(&(lock_cs[i]));
       }
  OPENSSL_free(lock_cs);
  OPENSSL_free(lock_count);
  }

  int main(){

   BN_CTX *ctx;
   ctx = BN_CTX_new();

   omp_set_num_threads(158);
   #pragma omp parallel
   {

          int ID = omp_get_thread_num();
          BIGNUM *b,*e,*r,*m;
          b = BN_new();
          e = BN_new();
          r = BN_new();
          m = BN_new();
          BN_set_word(b, 9);
          BN_set_word(e, 3);
          BN_set_word(m, 5);
          BN_mod_exp(r,b,e,m,ctx);
          char* result = BN_bn2dec(r);
          printf("\n thread = %d result = %s", ID, result); fflush(stdout);
          }

          thread_cleanup();

        }

我收到以下错误和回溯,它告诉我BN_mod_exp(r,b,e,m,ctx)是问题所在。

  Program received signal SIGSEGV, Segmentation fault.
  [Switching to Thread 0x7fffa9f69700 (LWP 151994)]
  0x00007ffff7a97bb6 in BN_CTX_end () from /lib/x86_64-linux-
  gnu/libcrypto.so.1.0.0
  (gdb) bt
  #0  0x00007ffff7a97bb6 in BN_CTX_end () from /lib/x86_64-linux-
  gnu/libcrypto.so.1.0.0
  #1  0x00007ffff7a940cd in BN_div () from /lib/x86_64-linux-
  gnu/libcrypto.so.1.0.0
  #2  0x00007ffff7aa3dff in BN_MONT_CTX_set () from /lib/x86_64-
  linux-gnu/libcrypto.so.1.0.0
  #3  0x00007ffff7a963e5 in BN_mod_exp_mont_word () from /lib/x86_64-
  linux-gnu/libcrypto.so.1.0.0
  #4  0x0000000000400fef in main._omp_fn.0 () at 
  debuggingsession.c:106
  #5  0x00007ffff77f734a in ?? () from /usr/lib/x86_64-linux-
  gnu/libgomp.so.1
  #6  0x00007ffff75d9184 in start_thread (arg=0x7fffa9f69700) at 
  pthread_create.c:312
  #7  0x00007ffff730603d in clone () at 
  ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
  (gdb) frame 4
   #4  0x0000000000400fef in main._omp_fn.0 () at 
   debuggingsession.c:106
  106       BN_mod_exp(r,b,e,m,ctx);
  (gdb) print r
  $1 = (BIGNUM *) 0x7fff8c000900
  (gdb) x 0x7fff8c000900
  0x7fff8c000900:   0x00000000
  (gdb) print b
   $2 = (BIGNUM *) 0x7fff8c0008c0
   (gdb) x 0x7fff8c0008c0
   0x7fff8c0008c0:  0x8c000940
   (gdb) x 0x8c000940
   0x8c000940:  Cannot access memory at address 0x8c000940
   (gdb) print b
   $3 = (BIGNUM *) 0x7fff8c0008c0
   (gdb) print e
   $4 = (BIGNUM *) 0x7fff8c0008e0
   (gdb) print m
   $5 = (BIGNUM *) 0x7fff8c000920
   (gdb) x

更新:我在一个更大的程序中使用OpenSSL和OpenMP,上面只是用于调试。在较大的程序中,我设置了多个线程,每个线程都应该写入自己的文件(不是同一个文件)。从这里:https://en.wikibooks.org/wiki/OpenSSL/Initialization他们说必须在初始化函数之前设置线程回调。我假设这意味着首先我们调用CRYPTO_thread_setup(),然后是OpenSSL库初始化函数。必须从哪里调用CRYPTO_thread_setup(),它是在第一个#pragma omp parallel之后和开始括号之前吗?当我把它放在那里,以及库初始化函数时,我仍然会遇到分段错误,这次涉及在线程中使用fclose()。关于为什么会发生这种情况的任何想法?

0 个答案:

没有答案