параллелизм — предотвращение создания процессов зомби в переполнении стека

Очень странная ошибка, возможно, кто-то увидит то, что мне не хватает.

У меня есть программа на C ++, которая разветвляется из оболочки bash, а затем передает ей команды.

Периодически команды будут содержать глупости, и процесс bash будет зависать. Я определяю это с помощью semtimedwait, а затем запускаю небольшую функцию, подобную этой:

if (kill(*bash_pid, SIGKILL)) {
cerr << "Error sending SIGKILL to the bash process!" << endl;
exit(1);
} else {
// collect exit status
long counter = 0;
do {
pid = waitpid(*bash_pid, &status, WNOHANG);
if (pid == 0) { // status not available yet
sleep(1);
}
if(counter++ > 5){
cerr << "ERROR: Bash child process ignored SIGKILL >5 sec!" << endl;
}
} while (pid != *bash_pid && pid != -1);
if(pid == -1){
cerr << "Failed to clean up zombie bash process!" << endl;
exit(1);
}

// re-initialized bash process
*bash_pid = init_bash();
}

Предполагая, что я правильно понимаю работу waitpid, он должен сначала отправить SIGKILL в оболочку, а затем по существу сидеть в спин-блокировке, пытаясь пожинать результат. В конце концов, это успешно, а затем запускается новый процесс bash с init_bash ().

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

Дополнительно:

  • Fork вызывается ровно в одном месте программы, внутри init_bash.
  • Проверки не позволяют вызывать init_bash, кроме как один раз при запуске программы и после вызова функции, указанной выше.

Мысли?

2

Решение

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

Эта статья предоставляет несколько способов убить зомби-процесс из командной строки. Одним из методов является использование других сигналов, кроме SIGKILL, например, SIGTERM.

это статья имеет ответ, который предлагает SIGKILL не должен использоваться.

Один из методов — убить родителя, тем самым убив его дочерние процессы, включая любых зомби. Автор указывает, что существуют дочерние процессы, которые остаются зомби до перезапуска ОС.

Вы не упомянули механизм, используемый для передачи команд дочернему процессу. Однако один из вариантов может заключаться в том, чтобы ослабить дочерний процесс, отсоединив его от его родителя, подобно тому, как дочерний процесс терминального процесса может быть отключен от сеанса терминала. Таким образом, ребенок станет его собственным процессом, и, если возникнет проблема, он может выйти, не став зомби.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]