这是自 R2012b (8.0) 以来已知的 MATLAB 的错误号 961964。MATLAB 使用静态 TLS 动态加载一些库(线程本地存储,例如参见 gcc 编译器标志 -ftls-model)。加载太多这样的库 => 没有剩余空间。
到目前为止,mathwork 唯一的解决方法是先加载重要的(!)库,并尽早使用它们(他们建议在 startup.m 中放入“ones(10)*ones(10);”)。我最好不要评论这个“解决策略”。
自 R2013b (8.2.0.701) 与 Linux x86_64 以来,我的经验是:不要使用“doc”(图形帮助系统)!我认为这个文档实用程序(libxul 等)正在使用大量静态 TLS 内存。
这是一个更新 (2013/12/31)
以下所有测试均使用 Fedora 20(带有 glibc-2.18-11.fc20)和 Matlab 8.3.0.73043(R2014a 预发行版)完成。
有关 TLS 的更多信息,请参阅 Ulrich Drepper,线程本地存储的 ELF 处理,版本 0.21,2013,目前可在Akkadia和Redhat获得。
究竟会发生什么?
MATLAB 动态(使用 dlopen)加载几个需要 tls 初始化的库。所有这些库都需要 dtv(动态线程向量)中的一个插槽。因为 MATLAB 在编译/链接时在运行时动态加载其中几个库,所以链接器(在 mathworks 中)没有机会计算所需的插槽(这是重要的部分)。现在动态库加载器的任务是在运行时处理这种情况。但这并不容易。引用 dl-open.c:
对于静态 TLS,我们必须在此时此地分配内存。这包括在 DTV 中分配内存。但是我们不能改变除我们自己的数字电视以外的任何数字电视。因此,如果我们不能保证 DTV 中有空间,我们甚至不会尝试并导致负载失败。
在 glibc 的动态库加载器中有一个编译时间常数(称为 DTV_SURPLUS,参见 glibc-source/sysdeps/generic/ldsodefs.h),用于为这种混乱保留一些额外的插槽(在多线程中动态加载具有静态 TLS 的库)程序)。在 Fedora 20 的 glibc 版本中,该值为 14。
在我的例子中,这是第一个需要 dtv 插槽的库(运行 MATLAB):
matlabroot/bin/glnxa64/libut.so
/lib64/libstdc++.so.6
/lib64/libpthread.so.0
matlabroot/bin/glnxa64/libunwind.so.8
/lib64/libuuid.so.1
matlabroot/sys/java/jre/glnxa64/jre/lib/amd64/server/libjvm.so
matlabroot/sys/java/jre/glnxa64/jre/lib/amd64/libfontmanager.so
matlabroot/sys/java/jre/glnxa64/jre/lib/amd64/libt2k.so
matlabroot/bin/glnxa64/mkl.so
matlabroot/sys/os/glnxa64/libiomp5.so
/lib64/libasound.so.2
matlabroot/sys/jxbrowser/glnxa64/xulrunner/xulrunner-linux-64/libxul.so
/lib64/libselinux.so.1
/lib64/libpixman-1.so.0
/lib64/libEGL.so.1
/lib64/libGL.so.1
/lib64/libglapi.so.0
是的,超过 14 个 => 太多 => dtv 中没有剩余插槽。这就是错误消息试图告诉我们的内容,尤其是 mathworks。
备案:为了不违反 MATLAB 的许可,我没有调试、反编译或反汇编 MATLAB 随附的二进制文件的任何部分。我只调试了 MATLAB 用来动态加载库的 Fedora 20 的免费和开放的 glibc 二进制文件。
可以做些什么来解决这个问题?
有 3 个选项:
(a) 重建 MATLAB 并且不动态加载这些库(使用 initial-exec tls 模型)而是链接它们(然后链接器可以计算所需的插槽!)
(b) 重建这些库并确保它们没有使用 initial-exec tls 模型。
(c) 重建 glibc 并在 glibc/sysdeps/generic/ldsodefs.h 中增加 DTV_SURPLUS
显然选项 (a) 和 (b) 只能由 mathworks 完成。
对于选项 (c),不需要 MATLAB 的源代码,因此可以在没有 mathworks 的情况下完成。
mathworks 的现状如何?
我真的试图向“MathWorks 技术支持部门”解释这一点。但我的印象是:他们不理解我。他们关闭了我的支持票,并建议在 2014 年 1 月与技术支持经理进行电话(!)对话。
我会尽力解释这一点,但说实话:我不是很自信。
更新 (2014/01/10):目前 mathworks 正在尝试选项 (b)。
更新 (2014/03/19):对于文件 libiomp5.so,您可以在 mathworks 下载新编译的版本(没有静态 TLS),错误报告 961964。和其他库?那里没有改善。所以不要惊讶于“dlopen: cannot load any more object with static TLS”和“doc”,例如参见错误报告 1003952。