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

查看:41
本文介绍了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 只是 unsigned 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 */ 
}

这不能简单地转换为 unsigned long,当我尝试这样做时,它会引发编译错误.我尝试将 void *p 转换为 unsigned long,理论上内存指针应该在线程间保持一致和唯一,但这只会导致我的程序崩溃很多.

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天全站免登陆