linux — создание закадрового контекста lib OSMesa не выполняется в C ++, но только в случае статической связи

Я создал инструмент C ++ для рендеринга 3D-моделей за пределами экрана. Рендеринг выполняется с использованием библиотеки OSMesa.

Программное обеспечение работало безупречно больше года, и я перестал обновлять его примерно 6 месяцев назад. Между тем, моя среда разработки обновлялась несколько раз.

Теперь я снова его компилировал и обнаружил неожиданную ошибку.

Обычная версия программного обеспечения все еще работала, как и ожидалось, но статически связанная версия — это segfaulting.

Я предполагаю, что ошибка моя в процедуре конфигурирования / компиляции / компоновки OSmesa, а не в коде библиотеки, но любые советы по улучшению отладки ошибки сегментации приветствуются.

Попробовав многочисленные варианты процесса компиляции без успеха, я теперь застрял.
Кто-нибудь может увидеть что-то глупое, что я делаю в некоторых шагах, описанных ниже?


Я перекомпилировал статическую версию библиотеки OSmesa с той же версией общей библиотеки, которая работает в моей системе (12.0.6), отключив все ненужные функции (с использованием системы на основе Ubuntu, статическая версия OSmesa lib отсутствует). доступно из репозиториев):

./ настроить \
--disable-xvmc \
--disable-glx \
--disable-dri \
--with-dri-drivers = "" \
--with-gallium-drivers = "" \
--disable-shared-glapi \
--disable-egl \
--with-egl-platform = "" \
--enable-osmesa \
--enable-gallium-llvm = нет \
--disable-gles1 \
--disable-gles2 \
--enable-static \
--disable-общий

Это команда компиляции моего внеэкранного инструмента рендеринга:

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: предупреждение: использование «dlopen» в статически связанных приложениях требует во время выполнения общих библиотек из glibc версия, используемая для ссылки

Вот что я получаю от запуска инструмента:

Ошибка сегментации (ядро сброшено)

Но ошибка сегментации не возникает, если я просто пропущу этап создания контекста OSmesa (и, очевидно, весь 3D-рендеринг)

Это обратный след:

# 0 0x0000000000000000 in ?? ()
# 1 0x00000000004af20a в mtx_init (тип = 4, mtx = 0xe10f70) в ../../include/c11/threads_posix.h:215
# 2 _mesa_NewHashTable () в main / hash.c: 135
# 3 0x000000000052f295 в _mesa_alloc_shared_state (ctx = ctx @ entry = 0xdcc9b0) в main / shared.c: 67
# 4 0x000000000046e717 в _mesa_initialize_context (CTX = CTX @ запись = 0xdcc9b0, апите = апи @ запись = API_OPENGL_COMPAT, визуальный =, share_list = share_list @ запись = 0x0, driverFunctions = driverFunctions @ запись = 0x7fffffffcd40) на главном / context.c: тысяча сто девяносто-две
# 5 0x000000000046c870 в OSMesaCreateContextAttribs (attribList = attribList @ entry = 0x7fffffffd290, sharelist =) в osmesa.c: 834
# 6 0x000000000046ccdc в OSMesaCreateContextExt (format =, deepBits =, stencilBits =, StorageBits =, sharelist =) в osmesa.c: 660
# 7 0x0000000000468742 в generate_thumbnail (Model *, Json :: Value) ()
# 8 0x0000000000401c7d в ​​основном (argc =, argv =) в ./src/measure_model.cpp:107

Статически связанный двоичный файл является строгим требованием.

Ошибка сегментации происходит на той же машине, которую я использую для компиляции инструмента (статическая библиотека OSmesa компилируется и на той же машине), но нет ошибки сегментации в не статически связанной версии того же инструмента.

3

Решение

Вот что я получаю от запуска инструмента:
Segmentation fault (core dumped)

Но ошибка сегментации не возникает, если я просто пропущу этап создания контекста OSmesa (и, очевидно, весь 3D-рендеринг)

Итак, есть проблема с созданием OSmesa. С вашей обратной трассировкой мы можем видеть, что функция 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

Какая была функция? В соответствии с онлайн источники включают / c11 / threads_posix.h: mtx_init() на GitHub, есть только звонки pthread_mutex_init, pthread_mutexattr_init и несколько других связанных с мьютексом функций libpthread (-lpthread).

Почему вместо реальной функции был произведен вызов NULL? Вероятно, из-за использования статической связи glibc и / или libpthread. Точная проблема до сих пор не определена (Мне удалось найти отчет о статически связанном libpthread.a в какую-то общую библиотеку, которая неверна и никогда не будет работать).

В вашем случае есть только псевдоним (сильный) из pthread_mutex_init в glibc / nptl / pthread_mutex_init.c (строка 150) strong_alias (__pthread_mutex_init, pthread_mutex_init) и может быть некоторый слабый псевдоним символа в самом glibc, вероятно, неинициализированный. Некоторые были не правы в ваших ссылках или / и в ld возражать, и он не нашел / связать nptl/pthread_mutex_init.o (это часть архива libpthread.a) с реальным символом в конечном исполняемом файле (ld часто пропускает неиспользуемые / ненужные объекты архивов .a и не связывает их в конечный исполняемый файл), сохраняя перемещение, указывающее на NULL. Какой-то эксперт по glibc может знать, Занятый русский является одним из экспертов по SO.

Я предлагаю связывать статически только со своими внутренними библиотеками или, возможно, также с обычными несистемными библиотеками, такими как mesa (вы можете использование -Wl,-Bstatic -lyour_lib -Wl,-Bdynamic варианты временного изменения связи со статической для библиотек, перечисленных между; или используйте чит-опцию -l: как -l:libYour_lib.a найден Радеком в том же д.). Но не связывайте статически с большинством базовых библиотек glibc, таких как libc, libpthread, librt (существуют некоторые проблемы статического связывания glibc, когда используется nss: целевая система должна иметь точно такую ​​же версию динамического glibc, чтобы nss работал).

Если вы хотите упаковать свое приложение для более старых машин и вам нужны некоторые функции glibc, вы можете также попытаться упаковать свою собственную версию совместно используемых библиотек glibc с вашим приложением; поместите их в некоторый подкаталог, добавьте rpath возможность компоновщика изменить пути поиска в библиотеке, а также изменить Раздел INTERP по умолчанию ABI ld-linux.so.2 загрузите вашу собственную копию ld-linux.so.2 из вашей версии glibc, … И у вас все еще будут проблемы со слишком старыми ядрами, поскольку для новых glibcs ​​требуются некоторые современные функции (системные вызовы, структуры) относительно нового ядра.

Или вы можете упаковать свое приложение в какой-то контейнер, такой как Docker, или какой-то другой изоляция решение (или chroot?), чтобы всегда иметь ваши версии библиотек …

ОБНОВЛЕНИЕ: Просто найденный отчет о подобном bt с NULL вместо реализации мьютекса из nptl: https://bugzilla.redhat.com/show_bug.cgi?id=163083 «Статически связанная программа на C ++ с использованием pthreads приведет к сбою» (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

По-видимому, это связано с тем, что некоторые функции pthreads не включены в исполняемый файл вывода. Эта ошибка может дублировать # 115157, и я прошу прощения, если так, но, надеюсь, включенный тестовый пример будет полезен.

Дополнительная информация:

Предложение в # 115157 принудительно ссылаться во всех файлах libpthread.a является допустимым обходным решением.

https://bugzilla.redhat.com/show_bug.cgi?id=115157 «исполняемые файлы, статически связанные с /usr/lib/nptl/libpthread.a fail» — 2004-2009 CLOSED WONTFIX

Jakub Jelinek 2004-10-29 05:26:10 ПО ВОСТОЧНОМУ ВРЕМЕНИ

Прежде всего, избегайте -static если вы можете, это только создает проблемы,
как с точки зрения мобильности, так и с другими.

Если вам действительно нужно создать статически связанный бинарный файл с -lpthread
связаны, то просто используйте -Wl,--whole-archive -lpthread -Wl,--no-whole-archive
вместо -pthread
. У всего остального действительно много проблем.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]