代码之家  ›  专栏  ›  技术社区  ›  Rudolfs Bundulis

STD::当使用静态LISTSTDC++时,线程弱,从而导致运行时崩溃

  •  1
  • Rudolfs Bundulis  · 技术社区  · 8 年前

    我需要构建一个可移植的共享对象,它是Linux上另一个软件的插件。我对这个主题做了大量的阅读,得出结论,我应该用一个相当老的glibc(提供与旧系统的兼容性)构建一个sysroot 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::线程 像ctor,dtor,swap,…定义为弱符号(如果加载插件的主机使用动态 libstdc++ 然后我的电话被转接到那里,所有的地狱都被释放了,对吗?).

    我进一步的谷歌搜索和阅读尝试并没有给我一个答案,我如何才能控制这一切,因为在 STD::线程 要分解成静态的东西 LIbSTDC++ 在我的系统根GCC中?

    另外,我做了一个小的可执行文件 dlopen 在我的共享对象上,然后调用一个内部构造线程的方法-如果可执行文件也是用 -静态libstdc++ 一切都很好,如果不是,车祸就发生了。所以我假设我关于 STD::线程 正在向主机解析 LIbSTDC++ 是正确的,但如何解决这个问题?

    1 回复  |  直到 8 年前
        1
  •  1
  •   Florian Weimer    8 年前

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

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

    作为一个即时的解决方案,您可以隐藏DSO中所有静态链接的libstdc++符号。然后不会发生任何干扰,DSO将实际使用DSO本身中的libstdc++副本,该副本已经确定过程中不应该有任何线程支持。

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

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