带有本地库的Perl模块:可以让xloader在dlopen上使用RTLD_GLOBAL

Perl modules with native libs: Possible to get XSLoader to use RTLD_GLOBAL on dlopen?

本文关键字:dlopen xloader GLOBAL RTLD Perl 模块      更新时间:2023-10-16

标题给出了简短的版本;它的长是我有一个c++ API包装到C &通过XS暴露给Perl。这已经工作了很多年了,但是我们现在遇到了一个用例,我们怀疑它可能是由重复加载公共库引起的。

症状是我们在Tibrv周围有一个内部Perl包装器。此外,我们还封装了另一个在内部使用Tibrv的c++ API。当Perl脚本同时使用这两个api时,第二个api依赖于创建Tib传输。单独地,两者都在Perl中工作。

我怀疑,但没有任何支持,它在某种程度上与共享状态和Perl有关,默认情况下加载带有RTLD_LOCAL集的库,可能导致这个问题(这是一个纯粹的预感)。我没有什么可以支持这一点,但我知道xz非常了解周围的环境,我认为这是有可能的。

我的问题:是否有可能使用dlopen标志,如RTLD_GLOBAL与Perl的XSLoader ?也就是说,当打开一个本地库而不重建Perl/XS时,可以改变dlopen标志吗?

到目前为止,我在网上看到的一切似乎都表明你需要使用DynaLoader,这将要求我们以适合从DynaLoader(目前不是)使用的方式重新构建我们的库(因为我们导出c++符号的方式)。

我只确定这将解决真正的问题,但是知道我们是否可以轻松地覆盖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不会为object可能使用的库调用dlopen,例如您遇到问题的库。