标题给出了缩略版;总而言之,我有一个 C++ API 包装到 C 并通过 XS 暴露给 Perl。这多年来一直运行良好,但我们现在遇到了一个用例,我们怀疑它可能是由公共(public)库的重复加载引起的。
症状是我们有一个围绕 Tibrv 的内部 Perl 包装器。而且,我们对内部使用 Tibrv 的另一个 C++ API 进行了包装。当 Perl 脚本同时使用这两个 API 时,第二个会在创建 Tib 传输时挂起。单独而言,两者都在 Perl 中工作。
我怀疑,但没有任何证据支持,它在某种程度上与共享状态和 Perl 有关,默认情况下加载带有 RTLD_LOCAL
设置的库,可能是导致问题的原因(这是一个纯粹的直觉)。我没有任何证据支持这一点,但我知道 Tib 非常了解周围的环境,我认为这有可能。
我的问题:
是否可以使用 dlopen
标志,例如 RTLD_GLOBAL
与 Perl 的 XSLoader
?即,可以在不重建 Perl/XS 的情况下打开 native 库时更改 dlopen
标志吗?
到目前为止,我在网上看到的一切似乎都表明您需要使用 DynaLoader,这将要求我们以适合从 DynaLoader (目前不是)。
我只有大约 10% 的把握这甚至可以解决真正的问题,但是知道我们是否可以轻松地覆盖 dlopen
标志将使我们可能节省几天的工作.
最佳答案
XSLoader 只是 DynaLoader 的前端。
听起来你可以添加
sub dl_load_flags { 0x01 }
到你的模块。这会被调用并传递给 flags
中的 dl_load_file
,它会执行以下操作:
if (flags & 0x01)
#ifdef RTLD_GLOBAL
mode |= RTLD_GLOBAL;
#else
Perl_warn(aTHX_ "Can't make loaded symbols global on this platform while loading %s",filename);
#endif
DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_load_file(%s,%x):\n", filename,flags));
handle = dlopen(filename, mode) ;
请注意,调用dl_load_file
以加载从您的.xs
编译的.so
。据我所知,XSLoader/DynaLoader 不会为对象可能使用的库调用 dlopen
,例如您遇到问题的库。
关于c++ - 带有 native 库的 Perl 模块 : Possible to get XSLoader to use RTLD_GLOBAL on dlopen?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15891589/