使用-static libstdc++时std::线程弱,因此在运行时会导致崩溃



我需要构建一个可移植的共享对象,它是Linux上另一个软件的插件。我对这个主题做了大量的阅读,得出的结论是,我应该用一个相当旧的glibc构建一个系统根的gcc(如果重要的话,gcc 5.4.0((以提供与旧系统的兼容性(,与-static-libstdc++-static-libgcc链接,这样我就有了只依赖于主机glibc和其他一些小东西的东西。

现在,我做了所有这些,现在我遇到了一个奇怪的崩溃——在代码调用std::thread的地方发生了分段错误,gdb实际上显示堆栈帧在libstdc++.so.6内部(不应该在哪里,我的共享对象的ldd也没有列出libstdc++.so(。崩溃时堆栈的顶部是:

#0  0x0000000000000000 in ?? ()
#1  0x00007ffff79075e3 in std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>, void (*)()) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 # THIS SHOULD NOT BE HERE RIGHT?
#2  0x00007ffff5a25a5c in std::thread::thread<void (ReferenceAnalytics::*)(std::timed_mutex&), ReferenceAnalytics*&, std::reference_wrapper<std::timed_mutex> >
(this=0x7fffffffcf40, __f=
@0x7fffffffcf60: (void (ReferenceAnalytics::*)(ReferenceAnalytics * const, std::timed_mutex &)) 0x7ffff5a1750c <ReferenceAnalytics::WorkerThreadMethod(std::timed_mutex&)>)
at /home/developer/Toolchains/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/include/c++/5.4.0/thread:137 # Looks like my toolchain

所以,我做了一些阅读,然后使用nm发现我的共享对象拥有所有std::thread的东西,比如ctor、dtor、swap。。。。定义为弱符号(我认为如果加载插件的主机使用动态libstdc++,然后我的调用被路由到那里,所有的地狱都会崩溃,这会导致冲突,对吗?(。

我在谷歌上搜索和阅读的进一步尝试并没有给我一个答案,即我如何控制这一点,因为强制将std::thread的内容解析为我的sysrooted gcc中的静态libstdc++

更重要的是,我制作了一个小的可执行文件,它只对我的共享对象执行dlopen,然后调用一个内部构造线程的方法——如果该可执行文件也是用-static-libstdc++构建的,那一切都很好,如果不是,就会发生崩溃。因此,我假设我关于std::thread的弱符号被解析为主机libstdc++的理论是正确的,但如何解决这个问题?

如果在不隐藏libstdc++符号的情况下,静态地将DSO链接到libstdcC++,并且主程序也链接到了libstdc+,那么当使用dlopen打开DSO时,主程序中的符号定义将插入/抢占DSO中的定义。

但是,由于主程序没有链接到libpthread,进程映像中的系统libstdc++DSO发现libpthred符号不可用(null(,因此禁用了线程支持。但是,您的DSO需要线程支持,但无法从系统libstdc++中获得。

作为一种即时的解决方法,您可以在DSO中隐藏所有静态链接的libstdc++符号。这样就不会发生插入,DSO实际上会在DSO本身中使用libstdc++副本,这已经确定了该过程中不应该有任何线程支持。

但这可能无法解决所有问题,因为通过dlopen加载libpthread的延迟会带来问题。我们在这里修复了一个错误:

  • 没有pthread的二进制文件后的Segfault dlopen((是与pthread链接的库

但是您的发行版可能没有这个修复程序,我预计还会有其他问题,其中之一是:这里实际上需要libstdc++的第二个静态链接副本,因为系统libstdc++是在没有线程支持的情况下加载的(因为libpthread在绑定其符号时没有加载,导致您观察到的崩溃(,所以您不能使用它来创建线程。它还激活了使库不具有线程安全性的优化(避免使用原子指令之类的东西(。

相关内容

  • 没有找到相关文章

最新更新