看workerman源码后自己写信号出现的疑问

haotian

源码 signal_fun.php

<?php  
// 设置信号处理函数  
function signal_handler($signo) {  
    switch ($signo) {  
         case SIGTERM:  
             // 处理SIGTERM信号  
             tlog("Caught SIGTERM...exit...\n");  
             exit;  
             break;  
         case SIGHUP:  
             //处理SIGHUP信号  
             tlog("Caught SIGHUP...\n");  
             break;  
         case SIGUSR1:  
             tlog("Caught SIGUSR1...\n");  
             break;  
         default:  
             // 处理所有其他信号  
     }  
}  

// 写日志  
function tlog($message, $print=1) {  
    $message = posix_getpid() . '_' . $message . "\n";  
    if ($print) {  
        echo $message;  
    } else {  
        error_log(posix_getpid() . '_' . $message . "\n", 3, '/var/www/log.log');  
    }  
}  

function _system($script) {  
    return system("/usr/local/php/bin/php /var/www/{$script} >> /var/www/system.log");  
}

源码 main.php

<?php  
include_once './signal_fun.php';  
tlog('im start run');  
declare(ticks=1);  

// 开启一个信号监控  
pcntl_signal(SIGTERM, 'signal_handler');  

$myids = array();  
while(1) {  
    for ($i = 0; $i < 5; ++$i) {  
        $mypid =pcntl_fork();       // 开启一个子进程,子进程和父进程同时从此处向下执行  
        if ($mypid < 0) {            // 子进程启动失败  
            tlog('fork error!');  
        } elseif ($mypid == 0) {    // 子进程中,读到的进程id为0  
            tlog('im child!');  
            sleep(1000);            // 子进程挂起   
            exit;  
        } else {                    // 父进程读到子进程的pid  
            $myids[] = $mypid;  
            sleep(1);  
        }  
    }  

    sleep(10);  
    if ($myids) {  
        foreach ($myids as $key => $pid) {  
            tlog('kill '. $pid);  

            posix_kill($pid, SIGTERM);          // 传递信号,kill 子进程  

            unset($myids);  

            sleep(2);  
        }  
    }  
}

完整的执行结果是这样

30834_im start run
30835_im child!
30836_im child!
30837_im child!
30838_im child!
30839_im child!
30834_kill 30835
30835_Caught SIGTERM...exit...

30834_kill 30836
30836_Caught SIGTERM...exit...

30834_kill 30837
30837_Caught SIGTERM...exit...

30834_kill 30838
30838_Caught SIGTERM...exit...

30834_kill 30839
30839_Caught SIGTERM...exit...

30860_im child!
30863_im child!
30866_im child!
30869_im child!
30872_im child!

先开启5个子进程,再杀死5个子进程,再开启...以此循环。

我想验证一下父进程关闭后,因为在main.php中声明了declare(ticks=1); 所以应该子进程时间到了之后关闭后,会自动去产生信号SIGTERM,由此也可以出现 30839_Caught SIGTERM...exit...这种提示,但是现在出现的问题是这样

# php main.php
2356_im start run
2357_im child!
2358_im child!
2359_im child!
2360_im child!
2361_im child!
^C
# kill -9 2357
-bash: kill: (2357) - 没有那个进程
# kill -9 2358
-bash: kill: (2358) - 没有那个进程
# kill -9 2359
-bash: kill: (2359) - 没有那个进程
# kill -9 2360
-bash: kill: (2360) - 没有那个进程
# kill -9 2361
-bash: kill: (2361) - 没有那个进程

ctrl+c关闭父进程之后,子进程没有了...

3337 2 0
2个回答

haotian

自己刚才试了试,现在把所有的过程粘贴到这边,希望后面遇到问题的有所启发
结论:使用ctrl c干掉父进程 那么一个进程组的子进程都会被干掉
使用kill -9 pid干掉父进程 子进程还存活着,说明这两个操作有本质上的不同

  • 暂无评论
haotian

补充一点 刚才@walkor 说的 ctrl c的时候会向所有该程序的进程包括子进程发送SIGINT信号的

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