1

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

XS 是标准的h2xs-lssl-lcrypto.Makefile

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 模块中并在线程外的 Perl 中使用它也可以。但是如果我在 Perl 和线程中使用它,它会崩溃。

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

我对 XS 很陌生,也许我错过了一些东西。也许有人可以给我一个提示,谢谢!

4

2 回答 2

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

SSL_library_init的文档中:

必须在任何其他操作发生之前调用 SSL_library_init()。SSL_library_init() 不可重入。

这意味着您最好SSL_library_init在线程启动之前调用一次,或者至少确保您有适当的锁定并且该函数不会被多次调用,包括不会从您可能使用的其他模块调用。从源代码中可以看出,Net::SSLeay这样的模块实际上会处理这个问题。

于 2016-08-25T04:25:50.197 回答
0

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

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

#include <openssl/ssl.h>

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

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

在我尝试让我的样本“漂亮”发布到这里后发现。这有点奇怪......我更喜欢编译器错误......

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

感谢帮助!!

于 2016-08-25T08:22:54.670 回答