我在用Helgrind报告libcrypto.1.0.0的CRYPTO_malloc()内数百种可能的数据争用测试多线程(pthreads)应用程序时遇到问题。
我已阅读并充分理解了所有可用的文档,包括《 Linux网络编程权威指南》第255-259页和http://www.openssl.org/docs/crypto/threads.html。
我的代码正在初始化静态和动态锁结构和回调,并注册线程ID回调:
CRYPTO_THREADID_set_callback(ssl_mitm_thread_id);
CRYPTO_set_dynlock_create_callback(ssl_mitm_dyn_create_lock);
CRYPTO_set_dynlock_lock_callback(ssl_mitm_dyn_locking_callback);
CRYPTO_set_dynlock_destroy_callback(ssl_mitm_dyn_destroy_lock);
ssl_mitm_lock_mutexes = (pthread_mutex_t*)malloc(CRYPTO_num_locks() *
sizeof(pthread_mutex_t));
for(i = 0; i < CRYPTO_num_locks(); i++) {
pthread_mutex_init(&ssl_mitm_lock_mutexes[i], NULL);
}
CRYPTO_set_locking_callback(ssl_mitm_locking_callback);
SSL_library_init();
SSL_load_error_strings();
...etc...
我已将调试语句添加到锁定回调函数中,并且openSSL仅调用已贬值的CRYPTO_set_locking_callback(),而不使用新的动态锁定接口(interface)。
即使这样,它正在调用旧的静态锁定函数,因此也在尝试进行线程同步,但是Helgrind仍然认为存在许多可能的数据争用。大多数(如果不是全部的话)都在CRYPTO_malloc()中。
那么,这个Helgrind是不是满腔热情还是OpenSSL/libcrypto中的错误?
例如
==20093== ----------------------------------------------------------------
==20093==
==20093== Possible data race during write of size 4 at 0x63BA368 by thread #3
==20093== Locks held: none
==20093== at 0x604F0FE: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==20093== by 0x57F4186: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==20093== by 0x57D20C4: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==20093== by 0x57D62E1: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==20093== by 0x57DF0B6: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
[snip] (SSL_connect() called)
==20093==
==20093== This conflicts with a previous write of size 4 by thread #6
==20093== Locks held: none
==20093== at 0x604F0FE: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==20093== by 0x57E1673: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
==20093== by 0x57DF359: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0)
[snip] (SSL_connect() called)
==20093==
==20093== ----------------------------------------------------------------
从SSL_read,SSL_write,SSL_connect和SSL_accept等调用的CRYPTO_malloc()中还有数据争用的其他示例。
最佳答案
下面的代码片段的最后一行是Helgrind提示的代码行:
void *CRYPTO_malloc(int num, const char *file, int line)
{
void *ret = NULL;
if (num <= 0) return NULL;
allow_customize = 0;
静态初始化中,
allow_customize
全局变量被初始化为1
。此值用于确保在调用分配例程本身之后不调用malloc定制函数(CRYPTO_set_mem...
和variants)。值0
的此设置是在锁之外执行的操作。从技术上讲,如果一个线程在尝试为CRYPTO_...alloc
设置自定义函数时另一个线程尝试调用CRYPTO
函数,则存在争用情况,但这可以视为应用程序错误。