Динамически загружаемая библиотека остается загруженной, несмотря на dlclose

Сегодня я ищу какое-то просветление о глубокой магии внутри динамического загрузчика. Я отлаживаю/устраняю неполадки системы плагинов для приложения C++, работающего в Linux. Он загружает плагины через dlopen (RTLD_NOW | RTLS_LOCAL) и выпускает их через dlclose. Ничего экстраординарного - можно было бы подумать.

Однако я заметил, что некоторые подключаемые модули остаются загруженными даже после успешного вызова dlclose*. Я пришел к такому выводу после просмотра карты памяти запущенного процесса с помощью pmap. Некоторые библиотеки немедленно удаляются из памяти процесса, а другие остаются, по-видимому, на неопределенный срок.

Далее на справочной странице dlopen говорится:

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

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

Я почти уверен (хотя и не на 100%), что счетчики ссылок равны нулю. Менеджер плагинов приложения обрабатывает все плагины одинаково. Это также гарантирует, что плагин не будет загружен несколько раз. Поэтому загрузка и выгрузка IMO должны вести себя одинаково для всех плагинов.

Это оставляет вторую возможность: другие загруженные библиотеки используют символы из плагинов. Еще один типичный случай «Этого никогда не должно случиться». Хотя конечно возможно. Мы используем gcc и видимость по умолчанию, и, насколько я знаю, ничего не удаляется, поэтому экспортируются тонны символов. На самом деле это беспокоит меня гораздо больше, так как эти плагины должны быть независимыми.

Вот мои открытые вопросы на данный момент:

  • Верны ли мои выводы на данный момент?
  • Знаете ли вы, как проверить счетчик ссылок для verifydlopen?
  • Если есть внутренние символы моих плагинов (случайно), используемые другими библиотеками, есть ли способ отследить, кто какие символы использует?

Моя машина: Linux 3.13.0-43-generic #72-Ubuntu SMP, понедельник, 8 декабря, 19:35:44 UTC 2014 i686 i686 i686 GNU/Linux

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


person djf    schedule 03.04.2015    source источник
comment
или другие загруженные библиотеки используют символы из некоторых, но не всех, плагинов. Я почти уверен, что ОС не может обнаружить это, по крайней мере, без сканирования всего пространства памяти процесса.   -  person Colonel Thirty Two    schedule 10.04.2015
comment
Используйте ltrace и/или strace, чтобы понять, по крайней мере, когда загружаются общие объекты.   -  person Basile Starynkevitch    schedule 10.04.2015
comment
@ColonelThirtyTwo Я согласен, отсюда и мое замешательство :) Возможно, я неправильно понимаю второй пункт предложения со страницы руководства dlopen выше.   -  person djf    schedule 10.04.2015
comment
Используйте также valgrind или скомпилируйте с gcc -fsanitize=address ; у вас куча может быть повреждена!   -  person Basile Starynkevitch    schedule 10.04.2015
comment
@BasileStarynkevitch Я не думал о повреждении кучи. Спасибо за предложения.   -  person djf    schedule 10.04.2015


Ответы (1)


другие загруженные библиотеки используют символы из плагинов

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

Для отладки компоновщика времени выполнения установите для переменной среды LD_DEBUG значение all, например. LD_DEBUG=all ./my_app. Подробнее см. man ld.so.

person Maxim Egorushkin    schedule 10.04.2015