2017-03-17 167 views
1

我有邏輯簽署其使用OpenSSL的方法,如SOAP文檔:多線程程序隨機崩潰

OpenSSL_add_all_digests, 
SSL_load_error_strings(); 
ERR_load_BIO_strings(); 
OpenSSL_add_all_algorithms(); 
OpenSSL_add_all_digests(); 
EVP_DigestUpdate 

等。當然,每個簽名文檔的邏輯運行在不同的線程中。

根據有關這個主題我創建靜態類用於處理線程的OpenSSL許多主題:

unsigned long SomeStaticClass::pthreads_thread_id(){ 
     unsigned long ret; 

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

void SomeStaticClass::pthreads_locking_callback(int mode, int type, const char* /*file*/, int /*line*/){ 

     if(mode & CRYPTO_LOCK){ 
       printf("CRYPTO_LOCK_MODE type: %d\n", type); 
       pthread_mutex_lock(&(lock_cs[type])); 
     } 
     else{ 
       printf("UNLOCK type: %d\n", type); 
       pthread_mutex_unlock(&(lock_cs[type])); 
     } 
} 

void SomeStaticClass::thread_setup(){ 

     printf("THREAD SETUP\n"); 
     lock_cs = (pthread_mutex_t*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); 
     for(int i = 0; i < CRYPTO_num_locks(); i++){ 
       pthread_mutex_init(&(lock_cs[i]), NULL); 
     } 

     CRYPTO_set_id_callback(SomeStaticClass::pthreads_thread_id); 
     CRYPTO_set_locking_callback(SomeStaticClass::pthreads_locking_callback); 
} 

void SomeStaticClass::thread_cleanup(){ 

     printf("THREAD CLEANUP\n"); 
     CRYPTO_set_id_callback(NULL); 
     CRYPTO_set_locking_callback(NULL); 
     for(int i = 0; i < CRYPTO_num_locks(); i++) { 
       pthread_mutex_destroy(&(lock_cs[i])); 
     } 

     OPENSSL_free(lock_cs); 
} 

我離開printf進行調試的目的。我知道其中的一些方法已被棄用,但我只能使用openssl 0.9.8。

我在runnig線程之前運行thread_setup,而在加入之後運行thread_cleanup。不幸的是,當我使用多線程時,我的應用程序仍然會隨機崩潰。我在pthreads_locking_callback被調用後得到SIGSEGV,因爲我在控制檯CRYPTO_LOCK_MODE type: 2上得到。根據回溯,它在調用OpenSSL_add_all_digests或EVP_DigestUpdate後崩潰。

所以問題是爲什麼OpenSSL崩潰,因爲我正在使用正確的方法處理多線程程序。我錯過了什麼?

編輯: ,因爲正如我所說,我已經使用這個經典的功能多線程應用程序它是不能重複的Tutorial on Using OpenSsl with pthreads

編輯2: 它的工作原理! 看起來@Matt Caswell是對的。感謝您的正確答案。

+0

[使用OpenSSL與pthreads的教程]的可能重複(http://stackoverflow.com/questions/3919420/tutorial-on-using-openssl-with-pthreads) –

+0

你怎麼知道這個問題是與OpenSSL和不是用你自己的代碼? –

+0

@AndrewHenle它在一個線程上完美工作,當我使用多線程時崩潰,並且它總是在openssl函數上崩潰。 – user1326505

回答

3

所有這些功能:

SSL_load_error_strings(); 
ERR_load_BIO_strings(); 
OpenSSL_add_all_algorithms(); 
OpenSSL_add_all_digests(); 

是庫初始化功能。您需要在調用其他OpenSSL函數之前調用它們一次。這些不是線程安全的。在設置您的鎖定回調之前調用它們。

+0

謝謝,我已經在一小時前做了,現在我正在測試它。到現在爲止還挺好。 – user1326505

+0

謝謝馬特。我不知道細節。它現在更新在[庫初始化| Static Locks](https://wiki.openssl.org/index.php/Library_Initialization)。 – jww