非常奇怪的错误,也许有人会看到我缺少的东西。
我有一个 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 进程,并继续正常执行。最终生成了太多的僵尸,系统用完了 pid。
此外:
- Fork 在程序中的一个地方被调用,在 init_bash 中。
- 检查会阻止调用 init_bash,除非在程序启动时和调用上述函数之后调用。
想法?