请教下pcntl 系列函数中信号机制的问题

blogdaren

假如是这样一种场景: 为了验证我的一些猜想,在PHP脚本内部, 我在父进程发送SIGTERM信号给其派生的所有子进程(也就是使用posix_kill函数发送SIGTERM信号), 期间使用了pcntl_signal注册信号,并设定了父进程的信号处理函数, 根据我理解的理论知识,如果没有设定SIGTERM信号处理函数,默认情况下posix_kill会执行SIGTERM信号的原始行为即终止子进程, 但是如果设定了SIGTERM信号处理函数(函数只是做了个echo而已), posix_kill的SIGTERM信号的原始行为就会被改变,但是经过试验,我发现所有的子进程还是被终止退出了....., 请问老大是我理解的信号机制有问题呢还是代码编写有问题?

另外我已经模拟编写了一个多进程PHP脚本,你看是否能帮看下这个脚本,谢谢?~~

2954 12 0
12个回答

walkor

要给子进程设置 SIGTERM信号处理函数,而不是父进程

  • 暂无评论
blogdaren

老大, 不好意思,是我表述不准确, 我是给子进程设置 SIGTERM信号处理函数~~

  • 暂无评论
walkor

把代码贴下吧

  • 暂无评论
blogdaren

详见: https:\/\/github.com\/blogdaren\/debug\/blob\/master\/fork.php

  • 暂无评论
blogdaren

老大, 我所在的群组无法发外部链接,代码比较多, 所以放在github上了, 上面贴的地址是json化的, 你json解码下地址然后访问看看~

  • 暂无评论
walkor

你的子进程终止是因为运行到了exit
https://github.com/blogdaren/debug/blob/master/fork.php#L303

  • 暂无评论
blogdaren

这个exit 我注意到过, 如果不写exit, 子进程就会继续向下执行脚本,也就是加上exit是防止其继续向下执行某些不应该执行的代码, 我试验了下, 去掉exit语句后, (终端命令: kill -2 主进程ID) 又会派生3-4倍数量的子进程, 还是迷惑很~

  • 暂无评论
walkor

额,自己理下吧

  • 暂无评论
blogdaren

老大, 我重新说下我的想法:

我贴的脚本只是个模拟脚本,实际绝对编程可能不这么用, 所以仅仅用于调试验证我根据理论知识得出的某种猜测想法,因为我找不到足够权威的资料来论证我的想法, 所以需要你帮我鉴定下脚本是否编写有问题已经我的结论是否正确。
我得出的结论是: 脚本启动后, 分别为父进程和子进程注册信号,然后在父进程给子进程发送SIGTERM信号,如果子进程没有设定信号捕捉函数,那么因SIGTERM进程就会被终止; 否则如果设定了信号处理函数, 并且这个函数只是简单的输出一句话完事儿,那么即便是捕捉到了SIGTERM信号,那么子进程也不应该退出(事实运行的结果是子进程赤裸裸的退出去了)
另外我发现我注释了子进程的register_ticks信号的信号代码, 居然子进程信号处理函数还能工作,无语
最后我修改了下模拟脚本,主要是模拟业务逻辑部分的代码, 而且脚本末尾写了大量的注释, 烦请你帮再看下, 非常感谢, 脚本地址: https:\/\/github.com\/blogdaren\/debug\/blob\/master\/fork.php

  • 暂无评论
walkor

现在代码没问题,
之前之所以退出是因为子进程运行到了exit。和信号没直接关系

  • 暂无评论
blogdaren

谢谢, 我找到问题的根本了, 经过大量的实践论证不是exit 的原因, 是348行处子进程信号相关代码有问题(pcntl_signal(SIGTERM, SIG_DFL) 是个关键), 非常感谢耐心的解答~~

  • 暂无评论
walkor

。。。
你没有找到问题的关键,之前子进程退出是因为子进程阻塞在sleep()系统调用,当收到信号后,sleep系统会立刻返回,导致start_business_worker函数就此执行完毕,直接运行到exit,子进程退出。

修改后的版本因为在子进程加了while{sleep},即使sleep遇到信号返回,但是因为还在while循环中,所以一直在start_business_worker,不会返回,所以没有问题。

  • 暂无评论
年代过于久远,无法发表回答
🔝