OpenSSL和多线程 [英] OpenSSL and multi-threads

查看:690
本文介绍了OpenSSL和多线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读有关在以下情况下使用OpenSSL的要求一个多线程应用程序,您必须向OpenSSL注册一个线程识别功能(以及一个互斥体创建功能).

I've been reading about the requirement that if OpenSSL is used in a multi-threaded application, you have to register a thread identification function (and also a mutex creation function) with OpenSSL.

在Linux上,根据OpenSSL提供的示例,通常通过注册如下函数来标识线程:

On Linux, according to the example provided by OpenSSL, a thread is normally identified by registering a function like this:

static unsigned long id_function(void){
    return (unsigned long)pthread_self();
}

pthread_self()返回一个pthread_t,这在Linux上有效,因为pthread_t只是一个无符号long的typedef.

pthread_self() returns a pthread_t, and this works on Linux since pthread_t is just a typedef of unsigned long.

在Windows pthreads,FreeBSD和其他操作系统上,pthread_t是具有以下结构的结构:

On Windows pthreads, FreeBSD, and other operating systems, pthread_t is a struct, with the following structure:

struct {
    void * p;                   /* Pointer to actual object */
    unsigned int x;             /* Extra information - reuse count etc */ 
}

这不能简单地强制转换为无符号长整型,而当我尝试这样做时,它会引发编译错误.我尝试使用void * p并将其强制转换为无符号长,这是基于以下理论:内存指针在线程之间应该是一致且唯一的,但这只会导致我的程序崩溃很多.

This can't be simply cast to an unsigned long, and when I try to do so, it throws a compile error. I tried taking the void *p and casting that to an unsigned long, on the theory that the memory pointer should be consistent and unique across threads, but this just causes my program to crash a lot.

在使用Windows pthreads或FreeBSD或任何其他这样的操作系统时,我可以向OpenSSL注册什么作为线程识别功能?

另外,还有一个问题:
有人知道如果将OpenSSL编译到QT中并与QT一起使用是否也需要这样做,以及如何在OpenSSL中注册QThreads?令人惊讶的是,我似乎找不到QT的答案文档.

Also, as an additional question:
Does anyone know if this also needs to be done if OpenSSL is compiled into and used with QT, and if so how to register QThreads with OpenSSL? Surprisingly, I can't seem to find the answer in QT's documentation.

推荐答案

我将在此处放置此代码.它不是万能药,因为它不能处理FreeBSD,但是在大多数情况下,当您需要的只是支持Windows并说Debian时,它就很有用.当然,干净的解决方案假定使用最近引入的CRYPTO_THREADID_*系列. (给出一个想法,它有一个CRYPTO_THREADID_cmp回调,可以映射到pthread_equal)

I will just put this code here. It is not panacea, as it doesn't deal with FreeBSD, but it is helpful in most cases when all you need is to support Windows and and say Debian. Of course, the clean solution assumes usage of CRYPTO_THREADID_* family introduced recently. (to give an idea, it has a CRYPTO_THREADID_cmp callback, which can be mapped to pthread_equal)

#include <pthread.h>
#include <openssl/err.h>

#if defined(WIN32)
    #define MUTEX_TYPE            HANDLE
    #define MUTEX_SETUP(x)        (x) = CreateMutex(NULL, FALSE, NULL)
    #define MUTEX_CLEANUP(x)      CloseHandle(x)
    #define MUTEX_LOCK(x)         WaitForSingleObject((x), INFINITE)
    #define MUTEX_UNLOCK(x)       ReleaseMutex(x)
    #define THREAD_ID             GetCurrentThreadId()
#else
    #define MUTEX_TYPE            pthread_mutex_t
    #define MUTEX_SETUP(x)        pthread_mutex_init(&(x), NULL)
    #define MUTEX_CLEANUP(x)      pthread_mutex_destroy(&(x))
    #define MUTEX_LOCK(x)         pthread_mutex_lock(&(x))
    #define MUTEX_UNLOCK(x)       pthread_mutex_unlock(&(x))
    #define THREAD_ID             pthread_self()
#endif

/* This array will store all of the mutexes available to OpenSSL. */ 
static MUTEX_TYPE *mutex_buf=NULL;

static void locking_function(int mode, int n, const char * file, int line)
{
    if (mode & CRYPTO_LOCK)
        MUTEX_LOCK(mutex_buf[n]);
    else
        MUTEX_UNLOCK(mutex_buf[n]);
}

static unsigned long id_function(void)
{
    return ((unsigned long)THREAD_ID);
}

int thread_setup(void)
{
    int i;

    mutex_buf = malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE));
    if (!mutex_buf)
        return 0;
    for (i = 0;  i < CRYPTO_num_locks(  );  i++)
        MUTEX_SETUP(mutex_buf[i]);
    CRYPTO_set_id_callback(id_function);
    CRYPTO_set_locking_callback(locking_function);
    return 1;
}

int thread_cleanup(void)
{
    int i;
    if (!mutex_buf)
        return 0;
    CRYPTO_set_id_callback(NULL);
    CRYPTO_set_locking_callback(NULL);
    for (i = 0;  i < CRYPTO_num_locks(  );  i++)
        MUTEX_CLEANUP(mutex_buf[i]);
    free(mutex_buf);
    mutex_buf = NULL;
    return 1;
}

这篇关于OpenSSL和多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆