LINUX.ORG.RU

нельзя вгрузить\выгрузить библиотеку, а потом сделать fork()

 , ,


0

1

нельзя вгрузить библиотеку [``dlopen()``], потом выгрузить [``dlclose()``] , а потом сделать ``fork()``...

....потому что будет «Segmentation fault» , если библиотека заиспользовала ``pthread_atfork()`` .

тык вот самое странное то, что Linux (и Posix) не имеют механизма, который бы смог бы подчистить за функцией ``pthread_atfork()``.

как такое смогли допустить? где логика?

почему например ``dlclose()`` не способен подчистить всё_это за функцией ``pthread_atfork()``?

зачем вообще разработчики придумали этот ``fork()`` , если до сих пор так и не смогли полностью *целостно* продумать всю-fork-концепцию?

# P.S. это просто «нытик-тред» .. тут меня можно просто поругать и посочувствовать мне :-)

# P.P.S. проверочный код тут: https://sourceware.org/bugzilla/attachment.cgi?id=6112 ( инструкция по компилированию в первом комментарии: https://sourceware.org/bugzilla/show_bug.cgi?id=13502 )

★★★★★

Последнее исправление: user_id_68054 (всего исправлений: 2)

Ну вопервых, fork вообще мало зачем нужен, а вовторых многие библиотеки в принципе не созданы выгружаемыми. Для этого их достаточно линковать с -Wl,-znodelete, вроде, и повторная загрузка/выгрузка им будет не страшна.

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

x11hater
()

потому что будет «Segmentation fault» , если библиотека заиспользовала ``pthread_atfork()`` .

А чего ты ожидал и каким образом должно достигаться ожидаемое тобой поведение?

tailgunner ★★★★★
()
Ответ на: комментарий от x11hater

fork вообще мало зачем нужен

это да.. и похоже что если и использовать fork — то только внутри «зиготы» (сфорканный на ранней стадии ребёнок, который потом если нужно опять форкается :)).

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

мне тут (в данной нытик-теме) обидно даже не за те случаи, когда программист «забыл» сделать свою библиотеку выгружаемой... :-)

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

user_id_68054 ★★★★★
() автор топика

Если либа твоя, то не прокатывает очистка списка коллбэков путём вызова сей функи, с нулями в качестве параметров?

pon4ik ★★★★★
()
Ответ на: комментарий от tailgunner

А чего ты ожидал и каким образом должно достигаться ожидаемое тобой поведение?

было бы не плохо, если бы в главном коде, когда я делаю ``dlclose()``, то пропадают все хуки которые были созданы функцией ``pthread_atfork()`` :-)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

Если либа твоя, то не прокатывает очистка списка коллбэков путём вызова сей функи, с нулями в качестве параметров?

не пробовал так.. но спасиб за подсказку :-)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

обидно даже не за те случаи, когда программист «забыл» сделать свою библиотеку выгружаемой... :-)

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

Вот как в моём случае:

http://lists.dragonflybsd.org/pipermail/users/2014-April/186955.html

x11hater
()
Ответ на: комментарий от pon4ik

> Если либа твоя, то не прокатывает очистка списка коллбэков путём вызова сей функи, с нулями в качестве параметров?

не пробовал так.. но спасиб за подсказку :-)

попробовал .. не , сработало :-)

очевидно каждый вызов ``pthread_atfork()`` — долько добавляет новые хуки (а не заменяет)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Ты не сказал, каким образом это должно достигаться.

а разве у ядра — нет информации о том какой хук относится к какой загруженной библиотеке?

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

а разве у ядра — нет информации о том какой хук относится к какой загруженной библиотеке?

O_O

Нет у ядра такой информации. И не должно быть by design.

tailgunner ★★★★★
()
Ответ на: комментарий от user_id_68054

Интересно, и странно. Интерфесы в позикс стандарта похожи на говно, но обычно позволяют всякое...

Ну, могу только посочувствовать :)

pon4ik ★★★★★
()
Ответ на: комментарий от tailgunner

O_O .. Нет у ядра такой информации

хорошо! :-)

я смотрю ты похож на того кто разбирается :-) [а не то что я «мимо проходил»]

расскажи — как так вышло, на практике?

почему это оказалось нереализуемо? (добавить хук можно, а удалить нельзя — что за такая проблема?)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

тык ведь в этом случае небось не будет полноценной выгрузки?

а нахрена тебе ее выгружать? ты хуки, которые ставишь через pthread_atfork, держишь в либе. хочешь ее выгрузить, и удивляешься сегфолтам после этого? странный ты пассажир

ananas ★★★★★
()
Ответ на: комментарий от user_id_68054

другой вариант - обнуляй хуки в деструкторе

ananas ★★★★★
()
Ответ на: комментарий от user_id_68054

А интерфейс в либе, тоже твой?

Может стоит подумать в сторону перекидывания бодяги с atfork на сторону клиентского кода? Типа сделать свой atfork, попросить юзверя передать 3 своих функи, дергающих функи из либы (ну или как то поизящнее извратиться) и на выходе у своих функ просто обнулять указатели, а пользователя заставить проверять не NULL ли функа.

Костыль? Костыль. Заработает? Заработает. Ну а фигли делать :)

pon4ik ★★★★★
()
Ответ на: комментарий от user_id_68054

расскажи — как так вышло, на практике?

Как «так» - что ядро не знает ничего о хуках и, тем более, отображении хуков на адреса? Потому что ядро обеспечивает более низкий уровень абстракции. Это тупо не его уровень ответственности.

почему это оказалось нереализуемо?

Убрать atfork-хук? Вероятно, это никому еще не понадобилось. Хуки вообще ставят перед вызовом fork. Зачем ты их ставишь сразу после загрузки библиотеки?

tailgunner ★★★★★
()
Ответ на: комментарий от ananas

а нахрена тебе ее выгружать?

незнаю зачем.

обычно это не нужно :-) ..

в серверных приложениях — темболее не знаю где это применить можно.

в GUI-программах — можно применить для подключения плагинов.

но в GUI-прогрммах обычно fork ни как не используется (кроме «зиготы» про которую выше(*) написал)

в целом проблема НЕ критичная.. но меня агрит её теоретическое существование, и что я должен выбирать между «выгружаемостью» и «форкаемостью» (получается что создавая библиотеку я не могу сделать её сразу одновременно: и «выгружаемой» и «форкаемой».. блин.. обидно же! :-))

ты хуки, которые ставишь через pthread_atfork, держишь в либе. хочешь ее выгрузить, и удивляешься сегфолтам после этого? странный ты пассажир

механизм из-за которого возникает «Segmentation fault» — я понимаю..

..но не понимаю почему нельзя удалить зарегистрированные хуки, которые указывают на адресное пространство библиотеки, которая вот щаз выгружается [dlclose()] :-)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Хуки вообще ставят перед вызовом fork

какой смысл использовать регистрацию хуков перед вызовом ``fork()`` , если вместо этого проще сразу выполнить нужные блокировки\разблокировки (без применения вообще какой-либо регистрации хуков) ?

Зачем ты их ставишь сразу после загрузки библиотеки?

потому что библиотека не знает в какой момент будет производиться ``fork`` и должна быть готова к нему — в *произвольный* момент времени. библиотека слегка приостановит ``fork()``в случае если ``fork()``в критически-важный момент.

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Как «так» - что ядро не знает ничего о хуках и, тем более, отображении хуков на адреса?

а каким образом корректно может сработать вызов ``dlclose()`` — если нет информации об адресах? :-)

предположим, что речь идёт просто об обычном ``dlopen()`` и ``dlclose()`` — без ``pthread_atfork()`` и без ``fork()`` .

ты имеешь ввиду что инфа об адресах есть не у ядра, а у <кого-то-другого> .. ну хорошо. значит претензия к этому <кому-то-другому> :-)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

какой смысл использовать регистрацию хуков перед вызовом ``fork()`` , если вместо этого проще сразу выполнить нужные блокировки\разблокировки (без применения вообще какой-либо регистрации хуков) ?

ЯННП. Если проще без хуков - зачем тебе вообще хуки?

Зачем ты их ставишь сразу после загрузки библиотеки?

потому что библиотека не знает в какой момент будет производиться ``fork``

Как всё запущено. Итак, ты должен ставить atfork-хуки перед вызовом fork и пока не назвал ни одной причины, которая помешала бы тебе так делать.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Как всё запущено. Итак, ты должен ставить atfork-хуки перед вызовом fork и пока не назвал ни одной причины, которая помешала бы тебе так делать.

я кажется понял! я слегка перефразирю тебя — наверно ты имеешь ввиду это:

"""Итак, ты НЕ должен ставить atfork-хуки ПОКА_НЕ окажешься перед вызовом fork"""

пока не назвал ни одной причины, которая помешала бы тебе так делать.

ну в принципе — да (ты прав) — ни чего же не мешает же мне сделать отдельную функцию в библитеке, назвать её например ``my_library__prepare_to_fork()`` — которая будет вызывать ``pthread_atfork()`` [ну или сразу будет делать нужные действия, без регистрации хуков]

и сделать *для_каждой* моей библиотеки такую функцию BLAHBLABLAH__prepare_to_fork()

# P.S.: правда часть проблемы всё равно останется — fork() пройдёт успешно, но *после* этого форка — нельзя будет выгрузить библиотеку и ещё раз сделать fork() :-D .... наверно придётся использовать ``clone()`` в этом случае [правда всё это высасоно из пальца уже :)] ..

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 5)

потому что форк придумал, когда твой папа пальцем в носу ковырялся. а птредс - уг, придуманное в 90х

anonymous
()
Ответ на: комментарий от user_id_68054

«„„Итак, ты НЕ должен ставить atfork-хуки ПОКА_НЕ окажешься перед вызовом fork““»

Да.

ни чего же не мешает же мне сделать отдельную функцию в библитеке, назвать её например ``my_library__prepare_to_fork()`` — которая будет вызывать ``pthread_atfork()``

facepalm.jpg

Тебе никто не мешает сделать в приложении функции add_fork_hook и del_fork_hook, а перед вызовом fork зарегистрировать через pthread_atfork то, что добавлено на данный момент. Или даже тупо вызвать это вообще без atfork.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Тебе никто не мешает сделать в приложении функции add_fork_hook и del_fork_hook, а перед вызовом fork зарегистрировать через pthread_atfork то, что добавлено на данный момент.

да

Или даже тупо вызвать это вообще без atfork.

именно так .. если я реализую эти ``add_fork_hook`` \ ``del_fork_hook`` [и буду самостоятельно вызывать зарегистрированные хуки] — то про функцию ``pthread_atfork()`` — можно вообще забыть :-)

блин, выходит эта функция ``pthread_atfork()`` — как пятая нога лошади (или как там эта поговорка звучит?) :-)

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 1)
Ответ на: комментарий от user_id_68054

выходит эта функция ``pthread_atfork()`` — как пятая нога лошади (или как там эта поговорка звучит?) :-)

Выходит, что для твоей задачи оно не нужно.

tailgunner ★★★★★
()

По-моему pthread_atfork получился, вообще, нерабочий. Фигня всякая происходит в дочернем процессе, если вызывается код, небезопасный относительно сигналов. Да, посикс несовершенен.

dave ★★★★★
()
Ответ на: комментарий от tailgunner

Выходит, что для твоей задачи оно не нужно.

да.. но если подытожить, то думаю...

...главная моя ошибка тут — нужно сразу принять за правило:

"""если хочу сделать выгружаемую библиотеку — НЕ использовать (внутри кода этой библиотеки) те функции которые НЕ имеют за собой подчищать .. пофиг-какими-хитрыми-способами выкручиваться, но не использовать!"""

а вот ``pthread_atfork()`` — это всего лишь как частный случай вышеназванного правила :-) !

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Ты не сказал, каким образом это должно достигаться

А в чём проблема добавить какой-нибудь pthread_delete_atfork, который будет принимать те же аргументы, что и atfork, только будет удалять их из списка хуков? Вызывать руками в библиотеке в функции с __attribute__((destructor)).

Gvidon ★★★★
()
Ответ на: комментарий от Gvidon

А в чём проблема добавить какой-нибудь pthread_delete_atfork, который будет принимать те же аргументы, что и atfork, только будет удалять их из списка хуков? Вызывать руками в библиотеке в функции с __attribute__((destructor)).

Зависимость от __attribute__((destructor)) - внезапно, POSIX != gcc. Кроме того, библиотека должна помнить список добавленных хуков. В результате это немногим лучше решений, приведенных выше.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.