Как избежать зомби-процессов после их выполнения в фоновом режиме - PullRequest
2 голосов
/ 21 мая 2010

мы программируем оболочку типа bash в C, но у нас есть проблемы с фоновыми процессами. Дело в том, что отец ждет дочернего процесса, когда нет &, мы сделали обработчик signal_handler для SIGCHLD, внутри которого есть ожидание.

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

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

Любая помощь может иметь первостепенное значение. Заранее большое спасибо.

1 Ответ

1 голос
/ 21 мая 2010

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

Когда вы создаете процесс, вы можете временно заблокировать 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 в обработчике сигналов, когда они умирают, чтобы вашему приложению было легче обрабатывать их и освобождать их память. Если вы хотите, чтобы дети не только умирали, но и умирали, это будет немного сложнее, потому что вы не захотите убирать их с живого стола. Может быть проще просто просмотреть таблицу в не сигнальном коде, чтобы найти измененные узлы. Если бы это было так, вы могли бы сделать это, не блокируя сигналы, кроме случаев, когда вы добавили или удалили узел.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...