python waitpid_waitpid使用的一点问题

python waitpid_waitpid使用的一点问题使用 waipid 的时候遇到了一个奇怪的问题 将情况简化后描述一下 示例代码如下所示 主进程会处理 SIGCHLD 信号 处理过程是等待子进程结束 如果子进程正常退出 打印捕获到了 SIGCHLD 信号 否则打印错误码 让主进程后面 sleep3s 是为了防止主进程先于子进程退出 从而没办法响应子进程的退出信号 测试正常 fork 的情况注释掉 capture2 和 testsystem 部分 使用 capture1 和 t

使用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 }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228115.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午7:47
下一篇 2026年3月16日 下午7:47


相关推荐

  • %d啥意思java_编程“%d”代表什么意思?

    %d啥意思java_编程“%d”代表什么意思?展开全部%d:表示把数据bai按十进制整型du输出。%o:表zhi示把数据按dao八进制整型版输权出。%x:表示把数据按十六进制整型输出。%u:表示把数据参数按无符号整型输出。%f:显示小数表示的普通浮点数。拓展资料:C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。尽管C…

    2022年7月9日
    25
  • oracle11g数据库导入导出方法教程[通俗易懂]

    oracle11g数据库导入导出方法教程[通俗易懂]oracle11g数据库导入导出:①:传统方式——exp(导出)和(imp)导入:②:数据泵方式——expdp导出和(impdp)导入;③:第三方工具——PL/sqlDevelpoer;一、什么是数据库导入导出?oracle11g数据库的导入/导出,就是我们通常所说的oracle数据的还原/备份。数据库导入:把.dmp格式文件从本地导入到数据库服务器中(本地oracle测试数据库中…

    2022年6月7日
    52
  • 统计学中的Bootstrap方法(Bootstrap抽样)

    统计学中的Bootstrap方法(Bootstrap抽样)Bootstrap 又称自展法 自举法 自助法 靴带法 是统计学习中一种重采样 Resampling 技术 用来估计标准误差 置信区间和偏差 Bootstrap 是现代统计学较为流行的一种统计方法 在小样本时效果很好 机器学习中的 Bagging AdaBoost 等方法其实都蕴含了 Boostrap 的思想 在集成学习的范畴里 Bootstrap 直接派生出了 Bagging 模型子样本之于样本 可以类比样本之于总体举例栗子 我要统计鱼塘里面的鱼的条数 怎么统计呢 假设鱼塘总共有鱼 10

    2026年3月26日
    2
  • 俄罗斯方块java版_俄罗斯方块 Java 版

    俄罗斯方块java版_俄罗斯方块 Java 版1packageersb 23 4 5 authorjiangn 7importjava applet Applet 8importjava applet AudioClip 9importjava awt 10importjava awt event 11importjava text DateFormat 12im

    2026年3月16日
    2
  • php Restful设计

    php Restful设计

    2021年10月22日
    57
  • springboot实现拦截器_spring拦截器和过滤器

    springboot实现拦截器_spring拦截器和过滤器集成拦截器登录验证为例添加拦截器public class LoginInterceptor implements HandlerInterceptor { private Logger log = LoggerFactory.getLogger(getClass()); //Controller逻辑执行之前 @Override public boolean preHandle(HttpServletRequest request, HttpServletRe

    2022年8月9日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号