非常奇怪的錯誤,也許有人會看到我失蹤的東西。避免在C++中生成殭屍進程
我有一個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的外殼,然後基本上是坐在一個自旋鎖,試圖收穫最終的過程。最終,它會成功,然後用init_bash()開始一個新的bash進程。
至少,這是應該發生的。相反,子進程的退出狀態永遠不會被收集,並且它會繼續作爲殭屍進程存在。儘管如此,父母確實退出循環並管理重新啓動bash進程,並繼續正常執行。最終會生成太多殭屍,並且系統將耗盡pid。
此外:
- 叉被稱爲在程序中的一個地方,裏面init_bash。
- 檢查防止init_bash被調用,除了在程序開始和調用上述函數之後。
想法?
一個正在運行的解決方法是調用signal(SIGCHLD,SIG_IGN);在主要的頂部,但這並不理想。我想直接收穫子進程。 –