В настоящее время я пытаюсь использовать многопоточность С++ 11 в общей библиотеке, которая загружается в основную программу (написанную на C) в Linux. Это часть большой симуляционной программы, и я ничего не могу изменить о загрузке библиотеки или изменении основной программы в целом.
Основная программа скомпилирована с gcc 4.1.2, и у меня нет источников для нее (я не могу перекомпилировать ее с помощью gcc 4.8.2).
Общая библиотека скомпилирована с помощью gcc 4.8.2, чтобы использовать многопоточность С++ 11. Я передаю команды компилятора
-pthread -lpthread -std=c++11
как описано в Каковы правильные параметры ссылок для использования std:: thread в GCC под Linux?
Компиляция автономной тестовой программы с этой конфигурацией ( "-pthread -std=c++11
" и gcc 4.8) корректно работает в моей системе. Но когда я запускаю загрузку программы в общую библиотеку, я получаю исключение:
Caught std::exception!
Exception Message: Enable multithreading to use std::thread: Operation not permitted
Terminating...
Использование -pthread
и -lpthread
( Изменить:, а также только -pthread
без -lpthread
) параметр компиляции не работает.
Аргументы компилятора (я использую систему сборки повара):
-pthread -std=c++11 -fmessage-length=0 -fPIC -Wchar-subscripts ...(lots of -W* here)
... -Wunused-variable -m64 -D__64BIT__ -pthread -lpthread
и аргументы компоновщика (дублирующие параметры из-за системы сборки):
-pthread -lpthread -std=c++11 -pthread -lpthread -std=c++11 -shared -fPIC -Wl,-Bsymbolic -Wl,--allow-shlib-undefined -pthread -lpthread
вызов ldd в моей библиотеке дает следующий вывод
$ ldd calc3/build/amd64_linux26_RH5/library.so
linux-vdso.so.1 => (0x00007fff4d1fd000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00002ae6ec124000)
libstdc++.so.6 => /afs/bb/data/d6833/util/gcc_482/lib64/libstdc++.so.6 (0x00002ae6ec340000)
libm.so.6 => /lib64/libm.so.6 (0x00002ae6ec655000)
libgcc_s.so.1 => /afs/bb/data/d6833/util/gcc_482/lib64/libgcc_s.so.1 (0x00002ae6ec8d8000)
libc.so.6 => /lib64/libc.so.6 (0x00002ae6ecaef000)
/lib64/ld-linux-x86-64.so.2 (0x00000032cb400000)
и в основной программе
$ ldd .../bin-64/main_program
linux-vdso.so.1 => (0x00007fff64595000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000032cc000000)
libz.so.1 => /usr/lib64/libz.so.1 (0x00000032cc800000)
libc.so.6 => /lib64/libc.so.6 (0x00000032cb800000)
/lib64/ld-linux-x86-64.so.2 (0x00000032cb400000)
Библиотека pthread связана с моей общей библиотекой, но не с основной программой. В этом ответе говорится, что вам нужно связать pthreads с основной программой, но второй комментарий к этому ответу (by @R..) говорит, что это необязательно (что звучит логически).
К сожалению, я ничего не знаю о механике загрузки всей системы, за исключением того, что моя библиотека использует другую библиотеку С++ как API.
Обратите внимание, что другие функции С++ 11 работают (и libstdС++, поэтому в зависимостях моей библиотеки), но многопоточность С++ 11 не является (хотя libpthread.so также находится в зависимостях моей библиотеки).
Использование класса потоковой передачи из библиотеки, содержащейся в самой программе, работает (и этот класс потоков также использует pthreads).
Я также пытался использовать -fabi-version=0
или -fabi-version=2
, потому что основная программа скомпилирована с помощью gcc 4.1.2 с моей библиотекой, но ничего не изменила.
Есть ли что-нибудь, что я упустил или вариант компилятора, который я могу использовать, чтобы заставить его работать? Или это кажется проблемой моей программной среды? Любые идеи приветствуются.
Edit:
Я попытался использовать -Wl,-no-as-needed
(как было предложено в комментариях), но, к сожалению, ничего не изменил.
Использование clang 3.5 вместо gcc 4.8 также не помогло.
Создание небольшого тестового приложения, которое загружает общую библиотеку (например, в ответе ниже @chill), работает (даже без флага компилятора), если я использую gcc 4.8 или clang 3.5 для основного приложения и общей библиотеки. При использовании gcc 4.1 для основной программы, однако, основная программа даже не загружает библиотеку (которая работает в моем "реальном" приложении). Я думаю, что может возникнуть проблема с отличительными ABI компиляторов.
Использование pthreads непосредственно из pthread.h
, похоже, работает (хотя программа в настоящее время завершается на pthread_join
без сообщения об ошибке, но я все еще там тестирую...)
Изменить 2:
Запуск "тестовой программы" с помощью LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
(потому что там тоже должны быть пути библиотеки gcc 4.8, спасибо @MvG) запустил программу, но снова с ошибкой Enable multithreading to use std::thread: Operation not permitted
.
Я проверил все остальные загружаемые библиотеки (нашел их с strace ./main_program 2>&1 | grep '^open(".*\.so"'
[см. здесь]) и проверил их все с помощью ldd
. Все они зависят от тех же библиотек (с теми же путями). ldd
выходы (для всех):
linux-vdso.so.1 => (0x00007fff4d3fd000)
libstdc++.so.6 => /afs/bb/data/d6833/util/gcc_482/lib64/libstdc++.so.6 (0x00002ade28774000)
libm.so.6 => /lib64/libm.so.6 (0x00002ade28ab0000)
libgcc_s.so.1 => /afs/bb/data/d6833/util/gcc_482/lib64/libgcc_s.so.1 (0x00002ade28d33000)
libc.so.6 => /lib64/libc.so.6 (0x00002ade28f49000)
/lib64/ld-linux-x86-64.so.2 (0x00000032ea200000)
(что все они не зависят от libpthread.so.0, кроме моей библиотеки и другого (но это то же самое /lib64/libpthread.so.0
))
В некоторых библиотеках есть больше зависимостей (которые не связаны с потоком), но, похоже, не существует каких-либо "конфликтных" зависимостей (нет зависимостей от разных версий/путей одной и той же библиотеки в любом из этих библиотеки).