Linux父進程未收到子進程退出信號SIGCHLD,而導致子進程成爲殭屍進程

在linux系統中,父進程通常會接收子進程SIGCHLD信號監測子進程是否退出,通過waitpid函數對子進程進行回收。但是實際應用過程中waitpid使用不當,會出現子進程成爲殭屍進程。原因在於,SIGCHLD信號是不可靠信號,不可靠信號在Linux中不進行排隊,只是放到一個緩衝區,一旦該信號解除阻塞則會立即被髮送一次(不可靠信號會丟失)。
任何一個子進程(init除外)在exit()之後,並非馬上就消失,而是留下一個稱爲殭屍進程(Zombie)的數據結構,等待父進程回收。由於SIGCHLD信號的丟失,如果父進程不進行回收處理,子進程就會一直處於殭屍狀態。
解決的辦法有兩個,一是在信號處理函數中,以非阻塞的方式調用waitpid,使用while循環,直到waitpid回收完所有等待回收的子進程。如下所示:
#include <sys/types.h> 
#include <sys/wait.h>
signal(SIGCHLD,sigchld_handler);
void sigchld_handler(int signo)
{
    pid_t pid;
    int status = 0;
    while((pid = waitpid(0,&status,WNOHANG)) > 0)
        cout<<"pid "<<pid<<" exited !"<<endl;
}

需要注意的是,waitpid函數第三個參數需要設置爲WNOHANG,這樣纔不會阻塞。
另外一種方式是在主線程或者創建線程中不停地while((pid = waitpid(0,&status,WNOHANG)) > 0),使得一有需要回收的子進程,就立馬進行回收。
參考博客:
1.Linux–測試信號阻塞及排隊
https://blog.csdn.net/Meteor_s/article/details/84999687?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
2.孤兒進程與殭屍進程[總結]
https://www.cnblogs.com/Anker/p/3271773.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章