gpt4 book ai didi

c++ - 避免在 C++ 中产生僵尸进程

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:30:34 24 4
gpt4 key购买 nike

非常奇怪的错误,也许有人会看到我遗漏的东西。

我有一个 C++ 程序,它派生出一个 bash shell,然后将命令传递给它。

周期性地,这些命令将包含废话并且 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 发送到 shell,然后实质上坐在自旋锁中,试图获取结果进程。最终,它成功了,然后使用 init_bash() 启动了一个新的 bash 进程。

至少,这是应该发生的事情。相反,子进程的退出状态永远不会被收集,它继续作为僵尸进程存在。尽管如此,父进程确实退出循环并设法重新启动 bash 进程,并继续正常执行。最终生成了太多的僵尸,系统耗尽了 pids。

另外:

  • Fork 仅在程序中的一个地方被调用,在 init_bash 中。
  • 检查防止 init_bash 被调用,除非在程序启动时和调用上述函数后调用一次。

想法?

最佳答案

我阅读的文章指出,僵尸进程的原因是子进程执行了退出,但父进程从未收集子进程的退出。

本文提供several ways to kill a zombie process from the command line .一种技术是使用除 SIGKILL 之外的其他信号,例如 SIGTERM。

article has an answer which suggests SIGKILL不应使用。

其中一种技术是杀死父进程,从而也杀死它的子进程,包括任何僵尸进程。作者指出,似乎有一些子进程在操作系统重新启动之前一直保持为僵尸进程。

您没有提到用于将命令传达给子进程的机制。然而,一种选择可能是通过断开子进程与其父进程的连接来释放子进程,类似于终端进程的子进程与终端 session 断开连接的方式。这样 child 就会成为自己的进程,如果有问题可以退出而不会变成僵尸。

关于c++ - 避免在 C++ 中产生僵尸进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12895392/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com