Ваш вопрос был немного неясен для меня, но я упомяну некоторые вещи, которые я думал о том, чтобы сделать для подобных ситуаций.
Когда вы создаете процесс, вы можете временно заблокировать SIGCHLD
и поместить запись дочернего процесса (и как он должен обрабатываться) в таблицу.
child_table_node_t * node = malloc(sizeof(child_table_node_t) );
// err check that
child_table_node_init(node, type_of_child_stuff);
sigset_t old, set;
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, &old);
pid_t pid = fork();
if (pid > 0) {
node->pid = pid;
add_to_table(alive_children, node);
sigprocmask(SIG_SETMASK, &old, NULL);
// other stuff
} else {
sigprocmask(SIG_SETMASK, &old, NULL);
if (!pid) {
// do child stuff
} else {
// do parent with no child stuff
}
}
Ваш handle_sigchild
может затем найти детей, которые умирают (или останавливаются, или что-то еще) в таблице, и сделать что-то для них. Я предлагаю удалить их из таблицы alive_children
и поместить их в таблицу dead_children
в обработчике сигналов, когда они умирают, чтобы вашему приложению было легче обрабатывать их и освобождать их память. Если вы хотите, чтобы дети не только умирали, но и умирали, это будет немного сложнее, потому что вы не захотите убирать их с живого стола. Может быть проще просто просмотреть таблицу в не сигнальном коде, чтобы найти измененные узлы. Если бы это было так, вы могли бы сделать это, не блокируя сигналы, кроме случаев, когда вы добавили или удалили узел.
Ваше приложение может затем выполнять действия, специфичные для умершего ребенка, на основе данных, хранящихся в узле таблицы для этого процесса. Если бы ребенок был на переднем плане, то его смерть (или действие остановки) состояла бы в том, чтобы сохранить код выхода в переменной кода выхода и снова начать принимать команды из терминала или сценария. Если недавно умерший ребенок был фоновым процессом, то вы просто записываете его код завершения и сообщаете его терминалу до следующей распечатки командной строки (если вы находитесь в интерактивном режиме).