как вызвать atexit в общей библиотеке?

В разделяемой библиотеке функция func1() имеет atexit(terminate_global), и эта разделяемая библиотека не имеет «атрибута ((конструктор))» и «атрибут (( деструктор))».
Итак, поток программы выглядит следующим образом:
1) Приложение загружает разделяемую библиотеку с помощью dlopen.
2) Приложения вызывают func1() с помощью dlsym.
3) func1() имеет atexit(terminate_global).
4) функция func1() возвращает значение.
5) Приложение вызывает dlclose для освобождения библиотеки.

В приведенных выше шагах я не обнаружил, что atexit() вызывается при выгрузке библиотеки. Итак, каким должен быть правильный способ, если atexit() должен вызываться, когда мы освобождаем разделяемую библиотеку? Должен ли я экспортировать подпрограммы, используя атрибуты функций attribute((constructor)) и attribute((destructor)), чтобы можно было вызвать зарегистрированную функцию atexit?


person Cloud30001    schedule 30.03.2015    source источник
comment
Приложение должно вызывать atexit(), а не библиотеку. Не усложняйте вещи. Если библиотеке нужна очистка, то она должна просто экспортировать некоторые функции, и приложение должно вызывать их при выходе.   -  person Matt    schedule 30.03.2015
comment
Какой вариант использования заставил вас задуматься об этом? Пожалуйста, отредактируйте свой вопрос, чтобы мотивировать его немного больше...   -  person Basile Starynkevitch    schedule 30.03.2015
comment
Обработчик atexit() запускается при закрытии самой программы, а не при выгрузке библиотеки/плагина. Для этого вам нужно добавить функцию деинициализации в вашу библиотеку.   -  person Galik    schedule 30.03.2015
comment
Привет, ребята, большое спасибо. Код (или поток кода), который я обсуждаю, представляет собой устаревший код, с которым я только что столкнулся. Я попытаюсь использовать некоторую деинициализацию или '__attribute__((destructor))', чтобы исправить это. Обновится обратно с рабочим решением.   -  person Cloud30001    schedule 31.03.2015


Ответы (1)


Я предполагаю, что функция terminate_global, переданная atexit, определена в плагине. Если terminate_global является глобальной функцией, определенной основной программой (связанной с флагом -rdynamic, чтобы ее символы обращались к подключаемым модулям), тогда подключаемый модуль может вызвать atexit(terminate_global), но тогда я бы предоставьте некоторую функцию API, делающую это.

Я не буду этого делать (вызывать atexit(terminate_fun) внутри какого-нибудь подключаемого модуля, где terminate_fun – это функция, определенная подключаемым модулем), если только вы не уверены, что ваше приложение никогда dlclose не выполняет плагин.

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

Вы должны определить, кто отвечает за dlclose установку плагина. Если ваше приложение явно делает это, вы можете либо выполнить некоторую очистку с помощью функции __attribute__((destructor)) C (или деструктора некоторых статических данных C++ в подключаемом модуле), либо определить и задокументировать соглашение, говорящее, например. что каждый плагин, у которого есть функция с именем plugin_cleanup (которую вы получите с dlsym), будет вызывать эту функцию очистки соответствующим образом.

В противном случае вы могли бы определить и задокументировать, что подключаемые модули не явно dlclose-d выполняются вашим приложением (часто это допустимо, в частности, если вы предлагаете какой-либо механизм очистки). Однако это может сделать valgrind несчастным.

person Basile Starynkevitch    schedule 30.03.2015
comment
Согласно code.google.com/p/android/issues/detail? id=6455 glibc это позволяет - person Plumenator; 31.03.2017