pcntl_wait调用问题

0

下面是我测试的代码,我发现如果在子进程中给父进程发送一个信号,如果使用pcntl_wait将会等待子进程退出才能执行
因为我使用php7.2测试的,所以是php版本导致?
我也看了网站里面的其他提问,冒失父进程都会阻塞到子进程退出


<?php
function stopAll($sig){
echo "master has a sig $sig\n" ;
}

$master_id = getmypid();

$pid = pcntl_fork();
if($pid > 0)
{
pcntl_signal(SIGINT,'stopAll') ;
pcntl_signal_dispatch();
$epid = pcntl_wait($status,WUNTRACED);
pcntl_signal_dispatch();
echo "parent process {$master_id}, child process {$pid}\n";
if($epid){
echo "child $epid exit \n" ;
}
}
else
{
$id = getmypid();
echo "child process,pid {$id}\n";
echo "send signal to master\n";
posix_kill($master_id, SIGINT);
sleep(60);
}
已邀请:

blogdaren - 乐于分享的PHP码农【http://www.blogdaren.com】

赞同来自: 默然

你虽然找到了关键的第三个参数,但是原理部分我认为理解错了呢,而且示例代码也是个问题代码:
1、你说的 "添加第三个参数 默认是true,这样子进程的sleep就不会执行了", 并不是这样的,子进程并未退出,而是休眠了,如果你写的不是sleep,而是死循环,那就成了典型的僵尸进程了【ps aux 或 strace下就会看到真相】
2、信号是可以中断 wait 等系统调用的
3、pcntl_signal(SIGINT,'stopAll',false) 函数的第三个参数是代表进程在收到信号后是内核是否重启系统调用。
4、根据上述条款2理论,示例代码中设置为false,那么主进程中 pcntl_wait立即被中断并返回了 -1,这个-1是代表异常出错了,而出错的原因是因为子进程并没有正常退出呢。
5、官方的 stopAll() 实现原理也完全不是你示例代码所写的那样的,大致原理是:
 (1) 父子进程均要安装信号处理器
 (2) 父进程负责收集子进程并监控起来等待子进程退出
 (3) 父进程会收到某种信号,之后将信号在发送给所有的子进程
 (4) 子进程收到信号后执行相应的逻辑处理并退出
 (5) 父进程若在约定期限依然尚未退出,则SIGKILL强行干掉

back0893

赞同来自:

因为我再看源码,在自己实现给父进程发送信号时方向,信号会被阻塞到子进程退出才会执行,,,,,
em,有点不明白stop是咋个实现的,因为我看源码也是给父进程发送一个信号
还是因为我是用cli没有用守护进程问题?

back0893

赞同来自:

还是手册没看明白
我知道了 pcntl_signal(SIGINT,'stopAll')
这里需要 添加第三个参数 默认是true,这样子进程的sleep就不会执行了 pcntl_signal(SIGINT,'stopAll',false) 父进程信号就会被立即执行,并且pcntl_wait返回的值是-1

要回复问题请先登录注册