Perl XS 中的 OpenSSL 和线程
OpenSSL and Threads in Perl XS
我正在 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-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 后发现。这有点奇怪....我更喜欢编译器错误...
但它解释了为什么另一个模块在工作。
感谢帮助!!
我正在 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-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 后发现。这有点奇怪....我更喜欢编译器错误...
但它解释了为什么另一个模块在工作。
感谢帮助!!