这是自 R2012b (8.0) 以来已知的 MATLAB 的 bug no 961964。 MATLAB 使用静态 TLS 动态加载一些库(线程本地存储,例如参见 gcc 编译器标志 -ftls-model)。加载太多这样的库 => 没有空间了。
到目前为止,mathwork 唯一的解决方法是先加载重要的 (!) 库,并尽早使用它们(他们建议将“ones(10)*ones(10);”放在 startup.m 中)。我最好不要评论这个“解决策略”。
自 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。所以,如果我们
不能保证我们没有的 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 个选项:
(一)
重建 MATLAB 并且不动态加载这些库
(使用 initial-exec tls 模型)而不是链接它们(然后是链接器
可以计算所需的插槽!)
(b)
重建这些库并确保它们没有使用 initial-exec tls 模型。
(c)
重建 glibc 并增加 DTV_SURPLUS in
glibc/sysdeps/generic/ldsodefs.h
显然选项 (a) 和 (b) 只能由 mathworks 完成。
对于选项 (c),不需要 MATLAB 的源代码,因此可以在没有 mathworks 的情况下完成。
在 mathworks 的状态如何?
我真的很想向“MathWorks 技术支持部门”解释这一点。但我的印象是:他们不理解我。他们关闭了我的支持票,并建议在 2014 年 1 月与技术支持经理进行电话(!)对话。
我会尽力解释这一点,但说实话:我不是很自信。
更新 (2014/01/10):目前 mathworks 正在尝试选项 (b)。
更新 (2014/03/19):对于文件 libiomp5.so,您可以在 mathworksbug report 961964 下载新编译的版本(没有静态 TLS)。和其他库?那里没有改善。所以不要惊讶于“dlopen: cannot load any more object with static TLS” with “doc”,例如见bug report 1003952。