python waitpid_waitpid使用的一点问题

使用waipid的时候遇到了一个奇怪的问题,将情况简化后描述一下。

示例代码如下所示。主进程会处理SIGCHLD信号,处理过程是等待子进程结束,如果子进程正常退出,打印捕获到了SIGCHLD信号,否则打印错误码。让主进程后面sleep 3s是为了防止主进程先于子进程退出,从而没办法响应子进程的退出信号。

测试正常fork的情况

注释掉capture2和test system部分,使用capture1和test fork。

正常的情况输出

this is parent.

this is child.

capture SIGCHLD1

视乎执行顺序,前两句有可能顺序反过来,即先执行子进程,后执行主进程后面的部分

测试system函数的情况

注释掉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,使用capture1、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

2 #include

3 #include

4 #include

5 #include

6 #include "errno.h"

7

8 voidSigChildFunc()9 {10 pid_t pid;11 intstatus;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 end24

25 //capture2 begin26 //pid = waitpid(-1, &status, WNOHANG);27 //if(pid > 0)28 //{29 //printf("capture SIGCHLD2\n");30 //}31 //else32 //{33 //printf("SigChildFunc error! errno=%d\n", errno);34 //}35 //capture2 end

36 }37

38 void SignalCB(intSignal)39 {40 switch(Signal)41 {42 caseSIGCHLD:43 SigChildFunc();44 break;45 default:46 break;47 }48 }49

50 intmain()51 {52 signal(SIGCHLD, SignalCB);53

54 //test system begin

55 system("ls");56 //test system end57

58 //test fork begin59 //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 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值