Perl XS 中的 OpenSSL 和线程

OpenSSL and Threads in Perl XS

我正在 Perl-XS-Module 中使用 OpenSSL。我有一个调用 OpenSSL-API-函数的 C 函数。它对于测试目的非常简单(初始化 openssl,读取密钥,创建 RSA 对象并使用它,没有参数)。不需要大检查,地址和内存都可以。

XS 是标准的 h2xs,-lssl-lcryptoMakefile.

void _foo (void)
{
    unsigned char key [3000];
    memset (key, 0, 3000);
    printf ("\ninit=%d", SSL_library_init ());   // init
    FILE *f = fopen ("key.key","r");
    printf ("\nf=%d", f);
    int keysize = fread (key, 1, 3000, f);   // readin
    printf ("\nn=%d",keysize);
    fclose (f);
    printf ("\nkey=%s", key);

    BIO *bio = BIO_new_mem_buf (key, keysize);
    printf ("\nbio=%ld", bio);
    RSA *pk = (RSA *) PEM_read_bio_RSAPrivateKey (bio, NULL, NULL, NULL);
    printf ("\npk=%ld", pk);

    printf ("\nsz=%d" ,RSA_size(pk));  // ***** crash here if in a perl-thread
    printf ("\n\n");
}

如果我做纯 C/C++,那是可行的。如果我将它放在 XS-Module 中并在线程外的 Perl 中使用它也可以。但如果我在 Perl 中和线程中使用它,它就会崩溃。

现在我会说那是因为我没有 thread-handling。但是如果我查看其他 Perl 模块(例如 Crypt::OpenSSL::RSA),我也没有找到特殊的线程处理。

我是 XS 的新手,也许我错过了什么。也许有人可以给我提示,谢谢!

printf ("\ninit=%d", SSL_library_init ());   // init

来自 SSL_library_init 的文档:

SSL_library_init() must be called before any other action takes place. SSL_library_init() is not reentrant.

这意味着您最好在线程启动之前调用 SSL_library_init 一次,或者至少确保您有适当的锁定并且该函数不会被多次调用,包括不会从您的其他模块调用可能会用。 Net::SSLeay actually take care of this as can be seen in the source code.

等模块

我找到了答案。我不确定,我不喜欢它,但它似乎是合法的。

我的 xs 中有很多 openssl-includes。但是我没有包括 ssl.h.

#include <openssl/ssl.h>

没有编译错误,没有链接器错误。如果我在线程中使用它,只会出现分段错误。甚至在线程外工作。

如果我包含 h 文件,一切正常。即使没有添加 openssl-mutex-thread-handling。

在我尝试将我的示例 "pretty" 制作成 post 后发现。这有点奇怪....我更喜欢编译器错误...

但它解释了为什么另一个模块在工作。

感谢帮助!!