我有一个嵌入式应用程序,它使用OpenSSL v0.9.7e进行客户端ssl事务。我一直在使用与子线程共享的全局会话指针。它监视每个COM端口有一个线程。它在很大程度上起作用。然而,每隔一段时间(每500个左右的事务)它就会在SSL_connect()内部崩溃。我做了一点点,它似乎是自己删除会话。因此,我怀疑其中一个线程在它执行时处于事务中间。如果参考计数是>我会认为它不会删除它。 0
有没有人知道是否可以通过全局共享会话执行此操作?我应该每个线程使用一个会话(COM端口)。这是代码。为简洁起见,我省略了所有错误检查。
int send_ssl_post(){
BIO *bio;
SSL *ssl;
int ret = -1;
int sockfd;
int sslRet;
ssl = NULL;
g_ctx = setup_client_ctx( );
ssl = SSL_new( g_ctx );
SSL_set_session( ssl, g_session );
sockfd = tcpConnect( url, true );
bio = BIO_new_socket( sockfd, BIO_NOCLOSE );
SSL_set_bio( ssl, bio, bio ); // SSL_set_bio cannot fail
sslRet = SSL_connect( ssl );
// free the session. We may change sessions below
if ( g_session != NULL ) {
SSL_SESSION_free( g_session );
}
// SSL write
ret = SSL_write( ssl, data, strlen( data ) );
ret = SSL_read( ssl, resp, respSize ); // time-out logic should be in
g_session = SSL_get1_session( ssl );
if ( ssl != NULL ) {
SSL_shutdown( ssl );
SSL_free( ssl );
}
if ( sockfd > 0 ){
close( sockfd );
}
ERR_remove_state( 0 ); // free the memory that did not freed (buggy in this SSL version)
return 0;
}
我还有两个thead锁定回调函数:
static void locking_function( int mode, int n, const char * file, int line ) {
if ( mode & CRYPTO_LOCK ){
//logger( DEBUG, "CRYPTO Lock file: %s, line: %d, n: %d", file, line, n );
pthread_mutex_lock( &ssl_mutex_array[n] );
} else {
//logger( DEBUG, "CRYPTO Unlock file: %s, line: %d, n: %d", file, line, n );
pthread_mutex_unlock( &ssl_mutex_array[n] );
}
}
static unsigned long id_function( void ) {
//logger( DEBUG, "CRYPTO Id function");
return ((unsigned long) pthread_self());
}
int setupSSLThreadLock( void ) {
int i;
//logger( DEBUG, "setupSSLThreadLock with %d number of locks", CRYPTO_num_locks() );
ssl_mutex_array = OPENSSL_malloc( CRYPTO_num_locks( ) * sizeof (pthread_mutex_t) );
if ( !ssl_mutex_array ){
return 0;
}
for ( i = 0; i < CRYPTO_num_locks( ); i++ ){
pthread_mutex_init( &ssl_mutex_array[i], NULL );
}
CRYPTO_set_id_callback( id_function );
CRYPTO_set_locking_callback( locking_function );
return 1;
}
int cleanupSSLThreadLock( void ) {
int i;
if ( ssl_mutex_array == NULL ){
return 0;
}
CRYPTO_set_id_callback( NULL );
CRYPTO_set_locking_callback( NULL );
for ( i = 0; i < CRYPTO_num_locks( ); i++ ){
pthread_mutex_destroy( &ssl_mutex_array[i] );
}
OPENSSL_free( ssl_mutex_array );
ssl_mutex_array = NULL;
return 1;
}
任何帮助将不胜感激。
答案 0 :(得分:1)
如果同时由两个线程运行send_ssl_post()
,则表示您有竞争。考虑函数的这两部分:
SSL_set_session( ssl, g_session );
和
// free the session. We may change sessions below
if ( g_session != NULL ) {
SSL_SESSION_free( g_session );
}
当一个线程在全局会话上调用SSL_SESSION_free()
和其他一些线程尝试使用它来设置会话之间存在争用。如果首先发生自由,则尝试使用它的线程将访问释放的内存。
您可以互相排斥解决此种族问题。一个围绕SSL_set_session()
电话。
acquire_session_lock();
if ( g_session != NULL ) {
SSL_set_session( ssl, g_session );
}
release_session_lock();
SSL_SESSION_free()
电话周围的另一个:
acquire_session_lock();
if ( g_session != NULL ) {
SSL_SESSION_free( g_session );
g_session = NULL;
}
release_session_lock();