LINUX.ORG.RU

Синхронизация процессов при fork()


0

0

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

Сейчас я ставлю обработчик SIGCHLD, смотрю на pid завершившегося процесса и нахожу доп. инфу о процессе в списке дочерних процессов. Вся проблема в том, что если дочерний процесс очень быстро закончится, то его код сохранения pid'а в таблице (т.е. кусок сразу после fork) будет выполнен после обработчика SIGCHLD, который соответственно не найдет инфы в таблице.

Как лечить?

Если делаете exec - тогда man vfork. И заполнить таблицу в дочернем процессе до exec.

svu ★★★★★
()

Отделить обработчик sigchld и логику, которую в него запихал? Обработчик будет ловить умерших детей и ложить в queue. Логика будет время от времени выгребать pid'ы из этого queue.

mv ★★★★★
()

слип после форка в дочке ?
дабы родитель успел произвести все препарации...

а вобще если ваш форк отрабатывает так быстро
это наводит на мысль что он не нужен
и дизайн который вы задумали крив до безобразия

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

>слип после форка в дочке ? дабы родитель успел произвeсти все препарации...

потенциальный race, перед форком маскировать обработку сигналов. ИМХО, это более правильно. И pid потомка можно занести в структуру и в протомке первым делом переопределить обработчики сигналов (если надо).

P.S. 2generatorglukoff. Надеюсь, что после получения сигнала SIGCHLD wait() вызывается в цикле с флагом WNOHANG пока wait() не вернет -1, так как не гарантируется доставка SIGCHLD на каждый порожденный процесс...

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

Крвовато написал. То есть "слип после форка в дочке" --- это потенциальный race condition. Так как в случае большой нагрузки (большого количества выполняемых процессов) не гарантируется время, через которое родительский процесс продолжит свое выполнение). Лучше всего маскировать сигналы (для простоты кода можно маскировать все сигналы) перед вызовом fork().

mky ★★★★★
()

Ждёшь завершения с помощью waitpid, а потом обрабатываешь код завершения и дальше ждёшь.

grishkin
()

Нити, семафоры и мьютексы уже не кашерно?

marsijanin ★★
()

> Как лечить?

лоботомией

anonymous
()

clone(CLONE_PARENT_SETTID, ptr_to_the_child_pid) instead of fork(), or

sigprocmask(SIG_BLOCK, {SIGCHLD});
pid = fork();
add_to_database(pid);
sigprocmask(SIG_UNBLOCK, {SIGCHLD});

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

> sigprocmask(SIG_BLOCK, {SIGCHLD}); pid = fork(); add_to_database(pid); sigprocmask(SIG_UNBLOCK, {SIGCHLD});

а почему блокирование сигнала SIGCHLD запретит ребенку завершиться??

dilmah ★★★★★
()

Зачем эти сигналы нужны? Можно ведь просто использовать waitpid?

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

surely the blocked SIGCHLD can't prevent the child
from exiting. but it blocks the signal until the
parent adds the pid to its internal database.

this means that the signal handler won't be confused
seeing the unregistered pid.

idle ★★★★★
()

> Сейчас я ставлю обработчик SIGCHLD, смотрю на pid завершившегося процесса и нахожу доп. инфу (...)

Основная ошибка: этого _нельзя_ делать в обработчике SIGCHLD. Там можно выставить флажок "нам помахали SIGCHLD'ом" и всё. Сдохший потомок будет висеть зомбяком до тех пор пока родитель не удосужится поинтересоваться его статусом через waitpid. А до вызова waitpid можно заполнить все необходимые таблицы и т.д.

anonymous
()

Ребенок сам может добавить себя в базу, получив свой номер из getpid(). Дочерний процесс точно не умрет, до того как зарегистрируется. Только не забудте про синхронизацию доступа к базе детей.

anonymous
()

2mv: я развил эту идею. Достаточно одного флажка "процесс умер, но инфы о нем записано еще не было", т.к. в один момент времени может быть не более одного такого процесса (т.е. об остальных процессах инфа точно есть). После форка проверяется состояние этого флажка и в случае необходимости вызывается логика обработки завершения (такая же, как и при SIGCHLD).

2mky: спасибо за цикл. Ибо в манах ничего не написано (ну или я совсем ослеп), что SIGCHLD может и не прийти.

PS. Вобщем-то [Solved]

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

>После форка проверяется состояние этого флажка и в случае необходимости вызывается логика обработки завершения (такая же, как и при SIGCHLD).

Как засинхронизировал добавление учетной информации о ребенке в потоке с форком и его чтение/удаление в обработчике сигнала? Здесь точно не подходят обычные мутексы, так как возможен деадлок... Вариант mky и idle с временным блокированием сигнала идеален во всех отношениях.

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

>Как засинхронизировал добавление учетной информации о ребенке в потоке с форком и его чтение/удаление в обработчике сигнала?

Форк происходит в том же потоке, что и обработчик сигнала. В обработчике сигнала есть две ситуации: вся инфа записана (а поле pid'а заполняется последним) либо нет (т.е. в списке не нашли инфу к процессу с таким pid'ом).

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

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

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

>В противном случае после форка только найдете место в списке куда добавить, в этот момент доходит сигнал и обработчик удаляет из списка все завершенные процессы, структура бызы полностью меняется, после возвращения из сигнала запишите по невалидному адресу.

Для обхода этой ситуации у меня в списке есть пустые элементы, куда можно записать информацию. Таким образом, при удалении информации структура базы не меняется, только при добавлении в отсутствии свободных мест. Платой этому есть некоторый расход памяти на простаивающие элементы, но это совсем копейки.

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