使用OpenSSL和锁定的多线程程序随机崩溃

时间:2017-03-17 08:23:52

标签: c++ linux multithreading openssl

我有使用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。根据backtrace,它在调用OpenSSL_add_all_digests或EVP_DigestUpdate后崩溃。

所以问题是为什么OpenSSL崩溃,因为我正在使用适当的方法来处理多线程程序。我缺少什么?

修改 它不是Tutorial on Using OpenSsl with pthreads的重复,因为正如我所提到的,我已经将这个经典函数用于多线程应用程序。

EDIT2: 有用! 看起来像@Matt Caswell是对的。谢谢你的正确答案。

1 个答案:

答案 0 :(得分:3)

所有这些功能:

<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true"/>

    <permission
        android:name="com.example.permission.MAPS_RECEIVE"
        android:protectionLevel="signature"/>
    <uses-permission android:name="com.example.permission.MAPS_RECEIVE"/>

初始化是否正常运行。您应该在调用其他OpenSSL函数之前调用它们一次。这些不是线程安全的。在设置锁定回调之前调用它们。