使用waipid的時候遇到了一個奇怪的問題,將狀況簡化後描述一下。html
有關waitpid的基本介紹參見這裏一下:http://www.cnblogs.com/mickole/p/3187770.html函數
示例代碼以下所示。主進程會處理SIGCHLD信號,處理過程是等待子進程結束,若是子進程正常退出,打印捕獲到了SIGCHLD信號,不然打印錯誤碼。讓主進程後面sleep 3s是爲了防止主進程先於子進程退出,從而沒辦法響應子進程的退出信號。測試
測試正常fork的狀況this
註釋掉capture2和test system部分,使用capture1和test fork。lua
正常的狀況輸出spa
this is parent.
this is child.
capture SIGCHLD1code
視乎執行順序,前兩句有可能順序反過來,即先執行子進程,後執行主進程後面的部分htm
測試system函數的狀況blog
註釋掉capture2和test fork部分,使用capture1和test system部分。進程
輸出以下
a.out waitpid.c
SigChildFunc error! errno=10
可見這裏waitpid出錯了,沒獲得子進程的退出狀態,其中errno 10表示No child processes(errno定義見http://baike.baidu.com/view/3485007.htm),不過並不妨礙system正確執行命令。
緣由在於system函數內部會經歷fork()->exec()->waitpid()三個階段,而咱們的主函數中有處理SIGCHLD信號,裏面還有waitpid操做。system自己的waitpid操做已經爲子進程收屍過了,後面那個就會找不到子進程。處理的一種方式能夠參見http://www.verydemo.com/demo_c167_i3191.html中的故事,我使用了另外一種方式:即只waitpid我fork出的子進程,別的忽略掉,即waitpid的第一個參數不傳-1,而是child_pid。
測試連續兩次waitpid的狀況
註釋掉test system,使用capture一、capture2和test fork部分。
輸出以下
this is parent.
this is child.
capture SIGCHLD1
SigChildFunc error! errno=10
一樣獲得了一次errno=10的錯誤。這說明不能連續嘗試2次waitpid。
題外話
在lua中,os.execute等同於c中的system函數,所以若是主進程執行lua邏輯,同時在處理SIGCHLD信號時使用waitpid捕獲子進程退出狀態,那麼lua中使用os.execute時須要注意這一點。
1 #include <sys/wait.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include "errno.h" 7 8 void SigChildFunc() 9 { 10 pid_t pid; 11 int status; 12 13 // capture1 begin 14 pid = waitpid(-1, &status, WNOHANG); 15 if(pid > 0) 16 { 17 printf("capture SIGCHLD1\n"); 18 } 19 else 20 { 21 printf("SigChildFunc error! errno=%d\n", errno); 22 } 23 // capture1 end 24 25 // capture2 begin 26 // pid = waitpid(-1, &status, WNOHANG); 27 // if(pid > 0) 28 // { 29 // printf("capture SIGCHLD2\n"); 30 // } 31 // else 32 // { 33 // printf("SigChildFunc error! errno=%d\n", errno); 34 // } 35 // capture2 end 36 } 37 38 void SignalCB(int Signal) 39 { 40 switch(Signal) 41 { 42 case SIGCHLD: 43 SigChildFunc(); 44 break; 45 default: 46 break; 47 } 48 } 49 50 int main() 51 { 52 signal(SIGCHLD, SignalCB); 53 54 // test system begin 55 system("ls"); 56 // test system end 57 58 // test fork begin 59 // pid_t pid = fork(); 60 // if(pid < 0) 61 // { 62 // printf("fork error! errno=%d\n", errno); 63 // } 64 // else if(pid == 0) 65 // { 66 // printf("this is child.\n"); 67 // exit(0); 68 // } 69 // 70 // printf("this is parent.\n"); 71 // sleep(3); 72 // test fork end 73 74 return 0; 75 }