Как заставить общую библиотеку перезагружаться под Linux

Я разрабатываю общую библиотеку на С++ под Linux.

Есть ли способ перезагрузить код общей библиотеки, когда, например, доступна новая сборка?

Я думал об использовании dlclose и dlopen для перезагрузки, но первому нужен дескриптор, доступный только для запущенного процесса.

Есть идеи, как получить этот дескриптор из кода общей библиотеки? Любое лучшее решение всей идеи?

Я понимаю, что горячая замена опасна, но это значительно облегчит разработку и тестирование.


person ZeroCool    schedule 30.03.2017    source источник


Ответы (1)


Когда вы перестраиваете разделяемую библиотеку, адреса ее экспортированных символов могут измениться.

Следовательно, при перезагрузке разделяемой библиотеки все символы, импортированные ее пользователями, должны быть повторно разрешены.

Объекты с виртуальными таблицами, находящиеся в общей библиотеке, должны быть уничтожены перед выгрузкой общей библиотеки1.

Если библиотека была загружена автоматически ld.so, вы не можете перезагрузить ее.

Если приложение загрузило разделяемую библиотеку с помощью dlopen, тот же код необходимо запустить еще раз, чтобы повторно загрузить библиотеку и повторно разрешить символы.

Существует также локальное хранилище потока, которое может усложнить ситуацию.

Другими словами, слишком сложно заставить работать перезагрузку разделяемой библиотеки без ведома приложения.


1Однажды я исправлял интересную ошибку. Была общая библиотека, которая загружалась во время выполнения с помощью dlopen и выгружалась после использования. Приложение позже вылетит в std::cout деструкторе во время завершения. Оказалось, что общая библиотека выводит объекты Boost.Date_Time в std::cout. При этом библиотека будет std::cout.imbue создавать новую локаль с пользовательским объектом фасета из Boost.Date_Time (фасеты имеют виртуальные функции). Когда библиотека была выгружена, объект фасета все еще принадлежал этой локали, но его указатель vtable ссылался на виртуальную таблицу в выгруженной разделяемой библиотеке, что могло вызвать сбой при уничтожении фасета.

person Maxim Egorushkin    schedule 30.03.2017
comment
Спасибо @Maxim. Да, приложение использует dlopen для загрузки библиотеки, и я вижу это в файле strace. Хорошая точка зрения! Я также должен разрешать символы после каждой перезагрузки, что немного усложняет ситуацию. - person ZeroCool; 30.03.2017
comment
Интересный пример - очень хорошо подчеркивает воздействие. - person ZeroCool; 03.04.2017