У меня есть приложение, которое использует dlopen()
загрузить дополнительные модули. Приложение и модули построены на Ubuntu 12.04 x86_64 с использованием gcc 4.6, но для архитектуры i386. Затем двоичные файлы копируются на другую машину с точно такой же ОС и работают нормально.
Однако, если они скопированы в Ubuntu 12.04 i386, то некоторые (но не все) модули не смогут загрузить следующее сообщение:
dlopen: cannot load any more object with static TLS
Я подозреваю, что это вызвано использованием __thread
переменные. Однако такие переменные не используются в загруженных модулях — только в самом модуле загрузчика.
Может ли кто-нибудь предоставить дополнительную информацию, в чем может быть причина?
Я уменьшаю количество __thread
переменные и их оптимизация (с -ftls-model
и т.д.), мне просто интересно, почему это не работает на почти та же система.
Я подозреваю, что это вызвано использованием переменных __thread.
Правильный.
Однако такие переменные не используются в загруженных модулях — только в самом модуле загрузчика.
Неправильно. Вы не можете использовать __thread
самостоятельно, но какую-то библиотеку вы статически связываете в свой модуль является используя их. Вы можете подтвердить это с помощью:
readelf -l /path/to/foo.so | grep TLS
в чем может быть причина?
Модуль использует -ftls-model=initial-exec
, но следует использовать -ftls-model=global-dynamic
, Это чаще всего происходит, когда (некоторые из) кода связаны с foo.so
построен без -fPIC
,
Связывание не-fPIC
код в общую библиотеку невозможен x86_64
, но разрешено ix86
(и приводит ко многим тонким проблемам, как эта).
Обновить:
У меня есть 1 модуль, скомпилированный без -fPIC, но я не устанавливаю tls-модель вообще, насколько я помню, значение по умолчанию не initial-exec
initial-exec
для не-fPIC
код.Отсюда следует, что если вы связываете даже один не-fPIC
объект, который использует __thread
в foo.so
, затем foo.so
получает initial-exec
за все его TLS.
Так почему же это вызывает проблемы — потому что если используется initial-exec, то количество переменных tls ограничено (потому что они не выделяются динамически)?
Правильный.
Других решений пока нет …