lib OSMesa 屏幕外上下文创建在 C++ 中失败,但仅在静态链接时
lib OSMesa off-screen context creation fails in C++, but only when statically linked
我做了一个3D模型离屏渲染的C++工具。渲染是使用 OSMesa 库完成的。
该软件完美运行了一年多,大约 6 个月前我停止对其进行更新。同时我的开发环境更新了很多次
现在重新编译,发现一个意想不到的bug。
该软件的普通版本仍按预期工作,但静态链接版本出现段错误。
我假设错误是我在 OSmesa configuration/compilation/linking 过程中而不是在库代码中,但是任何关于更好地调试分段错误的建议都将受到赞赏。
在尝试了编译过程的多种变体后都没有成功,我现在完全陷入困境。
任何人都可以看到我在下面描述的某些步骤中所做的愚蠢行为?
我使用与我的系统 (12.0.6) 中相同版本的共享库重新编译了 OSmesa 库的静态版本,禁用了所有不需要的功能(使用基于 Ubuntu系统,存储库中没有可用的 OSmesa 库的静态版本):
./configure \
--disable-xvmc \
--disable-glx \
--disable-dri \
--with-dri-drivers="" \
--with-gallium-drivers="" \
--disable-shared-glapi \
--disable-egl \
--with-egl-platforms="" \
--enable-osmesa \
--enable-gallium-llvm=no \
--disable-gles1 \
--disable-gles2 \
--enable-static \
--disable-shared
这是我的离屏渲染工具的编译命令:
g++ -std=c++11 -Wall -O3 -g -static -static-libgcc -static-libstdc++ ./src/measure_model.cpp model.o thumbnail.o -o measure_model_debug -pthread -lOSMesa -ldl -lm -lpng -lz -lcrypto
这是我通过使用 OSMesa 进行静态编译时收到的警告,它甚至在一年前就出现在工作静态二进制文件中:
/home/XXX/XXX/backend/lambda/mesa/mesa-12.0.6/src/mesa/main/dlopen.h:52: warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
这是我从 运行 工具中得到的:
Segmentation fault (core dumped)
但如果我只是跳过 OSmesa 上下文创建步骤(显然还有所有 3D 渲染),则不会产生分段错误
这是回溯:
#0 0x0000000000000000 in ?? ()
#1 0x00000000004af20a in mtx_init (type=4, mtx=0xe10f70) at ../../include/c11/threads_posix.h:215
#2 _mesa_NewHashTable () at main/hash.c:135
#3 0x000000000052f295 in _mesa_alloc_shared_state (ctx=ctx@entry=0xdcc9b0) at main/shared.c:67
#4 0x000000000046e717 in _mesa_initialize_context (ctx=ctx@entry=0xdcc9b0, api=api@entry=API_OPENGL_COMPAT, visual=, share_list=share_list@entry=0x0, driverFunctions=driverFunctions@entry=0x7fffffffcd40) at main/context.c:1192
#5 0x000000000046c870 in OSMesaCreateContextAttribs (attribList=attribList@entry=0x7fffffffd290, sharelist=) at osmesa.c:834
#6 0x000000000046ccdc in OSMesaCreateContextExt (format=, depthBits=, stencilBits=, accumBits=, sharelist=) at osmesa.c:660
#7 0x0000000000468742 in generate_thumbnail(Model*, Json::Value) ()
#8 0x0000000000401c7d in main (argc=, argv=) at ./src/measure_model.cpp:107
静态链接二进制文件是一项严格要求。
分段错误发生在我用来编译该工具的同一台机器上(OSmesa 静态库也在同一台机器上编译),但同一工具的非静态链接版本没有分段错误。
This is what I get from running the tool:
Segmentation fault (core dumped)
But no segmentation fault is produced if I simply skip the OSmesa context creation step (and obviously all the 3D rendering)
因此,OS台面创建存在一些问题。通过你的回溯,我们可以看到 top 函数是从零的 EIP 执行的(跳转到 NULL / NULL 的调用),所以在 mtx_init
中调用了一些函数,这是 OS Mesa 上下文的一部分创造。
#0 0x0000000000000000 in ?? ()
#1 0x00000000004af20a in mtx_init (type=4, mtx=0xe10f70) at ../../include/c11/threads_posix.h:215
#2 _mesa_NewHashTable () at main/hash.c:135
#3 0x000000000052f295 in _mesa_alloc_shared_state (ctx=ctx@entry=0xdcc9b0) at main/shared.c:67
#4 0x000000000046e717 in _mesa_initialize_context (ctx=ctx@entry=0xdcc9b0, api=api@entry=API_OPENGL_COMPAT, visual=, share_list=share_list@entry=0x0, driverFunctions=driverFunctions@entry=0x7fffffffcd40) at main/context.c:1192
#5 0x000000000046c870 in OSMesaCreateContextAttribs (attribList=attribList@entry=0x7fffffffd290, sharelist=) at osmesa.c:834
#6 0x000000000046ccdc in OSMesaCreateContextExt (format=, depthBits=, stencilBits=, accumBits=, sharelist=) at osmesa.c:660
#7 0x0000000000468742 in generate_thumbnail(Model*, Json::Value) ()
#8 0x0000000000401c7d in main (argc=, argv=) at ./src/measure_model.cpp:107
函数是什么?根据online sources of include/c11/threads_posix.h: mtx_init()
on github,只有对pthread_mutex_init
、pthread_mutexattr_init
和libpthread (-lpthread
) 的其他几个互斥相关函数的调用。
为什么产生了对 NULL 的调用而不是真正的函数?可能是由于使用了 static linkage of glibc and/or libpthread。 目前还没有确定确切的问题(我能够找到静态 linked libpthread.a 到一些共享库的报告,这是不正确的,永远不会工作) .
在您的情况下,glibc/nptl/pthread_mutex_init.c(第 150 行)strong_alias (__pthread_mutex_init, pthread_mutex_init)
中只有 pthread_mutex_init
的别名(强别名),并且可能有一些符号的弱别名glibc 本身,可能未初始化。 linkor/and 在 ld
的想法中有些错误,他没有 find/link nptl/pthread_mutex_init.o
(它是 libpthread.a 存档的一部分) 将真正的符号放入最终的可执行文件中(ld 经常跳过 unused/unneeded .a 档案的对象并且不将它们 link 放入最终的可执行文件中),保持重定位指向 NULL。一些glibc的专家可能知道,Employed Russian是SO专家之一。
我建议只对您的内部库静态 link 或者也可能对像 mesa 这样的普通非系统库静态地 link (您可以 use -Wl,-Bstatic -lyour_lib -Wl,-Bdynamic
options to temporary change linkage to static for libs listed between; or use cheat option of -l:
as -l:libYour_lib.a
found by Radek 在同一个问题中)。但不要 link 静态地使用 glibc 的大多数基本库,如 libc、libpthread、librt(当使用 nss 时,glibc 的静态 linking 存在一些问题:目标系统必须具有完全相同的动态版本glibc 使 nss 工作)。
如果您想为旧机器打包您的应用程序并且您需要 glibc 的某些功能,您也可以尝试将您自己的共享 glibc 库版本与您的应用程序一起打包;将它们放在某个子目录中,添加 linker 的 rpath
选项以更改库搜索路径,还将 INTERP section from default ABI ld-linux.so.2 加载器更改为您自己的 ld-linux.so.2 副本glibc 的版本,......你仍然会遇到太旧内核的问题,因为较新的 glibcs 需要一些相当新内核的现代功能(系统调用,结构)。
或者您可以将您的应用程序打包到某种容器中,例如 Docker,或其他一些 isolation 解决方案(或 chroot?)以始终拥有您的库版本...
更新:只是 found report of similar bt with NULL instead of mutex implementation from nptl: https://bugzilla.redhat.com/show_bug.cgi?id=163083 "Statically linked C++ program using pthreads will segfault" (2005-2007) pthread_mutex_init(&lock, NULL);
g++ -g -static foo.cpp -o foo -lpthread
where #0 0x00000000 in ?? () #1 0x08048232 in main () at foo.cpp:7
This is apparently due to certain pthreads functions not being included in the output executable. This bug may duplicate #115157, and I apologize if so, but hopefully the included test case will be useful.
Additional info:
The suggestion in #115157 to forcibly link in all of libpthread.a is a valid workaround.
https://bugzilla.redhat.com/show_bug.cgi?id=115157 "executables linked statically with /usr/lib/nptl/libpthread.a fail" - 2004-2009 CLOSED WONTFIX
Jakub Jelinek 2004-10-29 05:26:10 EDT
First of all, avoid -static
if you can, it only creates problems,
both portability wise and others as well.
If you really need to create statically linked binary with -lpthread
linked in, then just use -Wl,--whole-archive -lpthread -Wl,--no-whole-archive
instead of -pthread
. Anything else has really many problems.
我做了一个3D模型离屏渲染的C++工具。渲染是使用 OSMesa 库完成的。
该软件完美运行了一年多,大约 6 个月前我停止对其进行更新。同时我的开发环境更新了很多次
现在重新编译,发现一个意想不到的bug。
该软件的普通版本仍按预期工作,但静态链接版本出现段错误。
我假设错误是我在 OSmesa configuration/compilation/linking 过程中而不是在库代码中,但是任何关于更好地调试分段错误的建议都将受到赞赏。
在尝试了编译过程的多种变体后都没有成功,我现在完全陷入困境。 任何人都可以看到我在下面描述的某些步骤中所做的愚蠢行为?
我使用与我的系统 (12.0.6) 中相同版本的共享库重新编译了 OSmesa 库的静态版本,禁用了所有不需要的功能(使用基于 Ubuntu系统,存储库中没有可用的 OSmesa 库的静态版本):
./configure \ --disable-xvmc \ --disable-glx \ --disable-dri \ --with-dri-drivers="" \ --with-gallium-drivers="" \ --disable-shared-glapi \ --disable-egl \ --with-egl-platforms="" \ --enable-osmesa \ --enable-gallium-llvm=no \ --disable-gles1 \ --disable-gles2 \ --enable-static \ --disable-shared
这是我的离屏渲染工具的编译命令:
g++ -std=c++11 -Wall -O3 -g -static -static-libgcc -static-libstdc++ ./src/measure_model.cpp model.o thumbnail.o -o measure_model_debug -pthread -lOSMesa -ldl -lm -lpng -lz -lcrypto
这是我通过使用 OSMesa 进行静态编译时收到的警告,它甚至在一年前就出现在工作静态二进制文件中:
/home/XXX/XXX/backend/lambda/mesa/mesa-12.0.6/src/mesa/main/dlopen.h:52: warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
这是我从 运行 工具中得到的:
Segmentation fault (core dumped)
但如果我只是跳过 OSmesa 上下文创建步骤(显然还有所有 3D 渲染),则不会产生分段错误
这是回溯:
#0 0x0000000000000000 in ?? () #1 0x00000000004af20a in mtx_init (type=4, mtx=0xe10f70) at ../../include/c11/threads_posix.h:215 #2 _mesa_NewHashTable () at main/hash.c:135 #3 0x000000000052f295 in _mesa_alloc_shared_state (ctx=ctx@entry=0xdcc9b0) at main/shared.c:67 #4 0x000000000046e717 in _mesa_initialize_context (ctx=ctx@entry=0xdcc9b0, api=api@entry=API_OPENGL_COMPAT, visual=, share_list=share_list@entry=0x0, driverFunctions=driverFunctions@entry=0x7fffffffcd40) at main/context.c:1192 #5 0x000000000046c870 in OSMesaCreateContextAttribs (attribList=attribList@entry=0x7fffffffd290, sharelist=) at osmesa.c:834 #6 0x000000000046ccdc in OSMesaCreateContextExt (format=, depthBits=, stencilBits=, accumBits=, sharelist=) at osmesa.c:660 #7 0x0000000000468742 in generate_thumbnail(Model*, Json::Value) () #8 0x0000000000401c7d in main (argc=, argv=) at ./src/measure_model.cpp:107
静态链接二进制文件是一项严格要求。
分段错误发生在我用来编译该工具的同一台机器上(OSmesa 静态库也在同一台机器上编译),但同一工具的非静态链接版本没有分段错误。
This is what I get from running the tool:
Segmentation fault (core dumped)
But no segmentation fault is produced if I simply skip the OSmesa context creation step (and obviously all the 3D rendering)
因此,OS台面创建存在一些问题。通过你的回溯,我们可以看到 top 函数是从零的 EIP 执行的(跳转到 NULL / NULL 的调用),所以在 mtx_init
中调用了一些函数,这是 OS Mesa 上下文的一部分创造。
#0 0x0000000000000000 in ?? ()
#1 0x00000000004af20a in mtx_init (type=4, mtx=0xe10f70) at ../../include/c11/threads_posix.h:215
#2 _mesa_NewHashTable () at main/hash.c:135
#3 0x000000000052f295 in _mesa_alloc_shared_state (ctx=ctx@entry=0xdcc9b0) at main/shared.c:67
#4 0x000000000046e717 in _mesa_initialize_context (ctx=ctx@entry=0xdcc9b0, api=api@entry=API_OPENGL_COMPAT, visual=, share_list=share_list@entry=0x0, driverFunctions=driverFunctions@entry=0x7fffffffcd40) at main/context.c:1192
#5 0x000000000046c870 in OSMesaCreateContextAttribs (attribList=attribList@entry=0x7fffffffd290, sharelist=) at osmesa.c:834
#6 0x000000000046ccdc in OSMesaCreateContextExt (format=, depthBits=, stencilBits=, accumBits=, sharelist=) at osmesa.c:660
#7 0x0000000000468742 in generate_thumbnail(Model*, Json::Value) ()
#8 0x0000000000401c7d in main (argc=, argv=) at ./src/measure_model.cpp:107
函数是什么?根据online sources of include/c11/threads_posix.h: mtx_init()
on github,只有对pthread_mutex_init
、pthread_mutexattr_init
和libpthread (-lpthread
) 的其他几个互斥相关函数的调用。
为什么产生了对 NULL 的调用而不是真正的函数?可能是由于使用了 static linkage of glibc and/or libpthread。 目前还没有确定确切的问题(我能够找到静态 linked libpthread.a 到一些共享库的报告,这是不正确的,永远不会工作) .
在您的情况下,glibc/nptl/pthread_mutex_init.c(第 150 行)strong_alias (__pthread_mutex_init, pthread_mutex_init)
中只有 pthread_mutex_init
的别名(强别名),并且可能有一些符号的弱别名glibc 本身,可能未初始化。 linkor/and 在 ld
的想法中有些错误,他没有 find/link nptl/pthread_mutex_init.o
(它是 libpthread.a 存档的一部分) 将真正的符号放入最终的可执行文件中(ld 经常跳过 unused/unneeded .a 档案的对象并且不将它们 link 放入最终的可执行文件中),保持重定位指向 NULL。一些glibc的专家可能知道,Employed Russian是SO专家之一。
我建议只对您的内部库静态 link 或者也可能对像 mesa 这样的普通非系统库静态地 link (您可以 use -Wl,-Bstatic -lyour_lib -Wl,-Bdynamic
options to temporary change linkage to static for libs listed between; or use cheat option of -l:
as -l:libYour_lib.a
found by Radek 在同一个问题中)。但不要 link 静态地使用 glibc 的大多数基本库,如 libc、libpthread、librt(当使用 nss 时,glibc 的静态 linking 存在一些问题:目标系统必须具有完全相同的动态版本glibc 使 nss 工作)。
如果您想为旧机器打包您的应用程序并且您需要 glibc 的某些功能,您也可以尝试将您自己的共享 glibc 库版本与您的应用程序一起打包;将它们放在某个子目录中,添加 linker 的 rpath
选项以更改库搜索路径,还将 INTERP section from default ABI ld-linux.so.2 加载器更改为您自己的 ld-linux.so.2 副本glibc 的版本,......你仍然会遇到太旧内核的问题,因为较新的 glibcs 需要一些相当新内核的现代功能(系统调用,结构)。
或者您可以将您的应用程序打包到某种容器中,例如 Docker,或其他一些 isolation 解决方案(或 chroot?)以始终拥有您的库版本...
更新:只是 found report of similar bt with NULL instead of mutex implementation from nptl: https://bugzilla.redhat.com/show_bug.cgi?id=163083 "Statically linked C++ program using pthreads will segfault" (2005-2007) pthread_mutex_init(&lock, NULL);
g++ -g -static foo.cpp -o foo -lpthread
where #0 0x00000000 in ?? () #1 0x08048232 in main () at foo.cpp:7
This is apparently due to certain pthreads functions not being included in the output executable. This bug may duplicate #115157, and I apologize if so, but hopefully the included test case will be useful.
Additional info:
The suggestion in #115157 to forcibly link in all of libpthread.a is a valid workaround.
https://bugzilla.redhat.com/show_bug.cgi?id=115157 "executables linked statically with /usr/lib/nptl/libpthread.a fail" - 2004-2009 CLOSED WONTFIX
Jakub Jelinek 2004-10-29 05:26:10 EDT
First of all, avoid
-static
if you can, it only creates problems, both portability wise and others as well.If you really need to create statically linked binary with
-lpthread
linked in, then just use-Wl,--whole-archive -lpthread -Wl,--no-whole-archive
instead of-pthread
. Anything else has really many problems.