waitpid使用的一點問題

使用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 }
相關文章
相關標籤/搜索