【PHP】PHP里针对while循环里的异常退出的处理

在自己设计的消息队列里,主要是一个while循环,通过while循环里不断去读取Redis队列里的参数,

来达到消息队列的目的。可是,有可能进程会被突然杀掉,或者被人为的kill掉,如果被强行kill掉后,

会导致while里的部分逻辑走不完,走不完会导致部分数据的丢失。

<?php
class ModTest {
    private $cnt = 0;
    // 构造函数,用来处理基本信息
    public function __construct() {
        pcntl_signal(SIGHUP, array($this, 'sigHandler'));
		pcntl_signal(SIGINT, array($this, 'sigHandler'));
		pcntl_signal(SIGQUIT, array($this, 'sigHandler'));
		pcntl_signal(SIGILL, array($this, 'sigHandler'));
		pcntl_signal(SIGFPE, array($this, 'sigHandler'));
		pcntl_signal(SIGALRM, array($this, 'sigHandler'));
		pcntl_signal(SIGTSTP, array($this, 'sigHandler'));
		pcntl_signal(SIGABRT, array($this, 'sigHandler'));
		pcntl_signal(SIGTERM, array($this, 'sigHandler'));

    	// shutdown
    	register_shutdown_function(array($this, 'shutdownHandler'));
    }
    public function startPush() {
        while (true) {
            PubFileLog::writeDebugInfo('before, cur num is : ' . $this->cnt);
            pcntl_signal_dispatch();
            $this->cnt++;
            PubFileLog::writeDebugInfo('after, cur num is : ' . $this->cnt);

            sleep(15);
            PubFileLog::writeDebugInfo('ssssssss');
        }
    }
    /**
     * 异常退出处理函数
    */
    public function shutdownHandler() {
        $data = error_get_last();
        PubFileLog::log(json_encode($data), '/tmp/***.log');
    }
    /**
     * 信号处理函数
     * @param int $signal
     */
    public function sigHandler($signal) {
        $data = array(
            'sig_no' => $signal,
        );
        PubFileLog::log(json_encode($data), '/tmp/***.log');
        switch ($signal) {
            case SIGHUP:
            case SIGINT:
            case SIGQUIT:
            case SIGILL:
            case SIGFPE:
            case SIGALRM:
            case SIGTSTP:
            case SIGABRT:
                break;
            case SIGTERM:
                // SIGTERM信号时,退出进程
                exit();
                break;
            default:
                break;
        }
    }
}



参考上面的代码,当我们执行startPush后,除非人为的把进程kill掉或者其他因素,那么这个循环就会一直执行下去。

我们可以在进程退出的时候,进行监测,除了SIGTERM($signal=15),其他情况下都是break。

而且当系统监测到是kill -15时,会等到执行完pcntl_signal_dispatch()这个函数才会正式退出(走到代码的sigHandler函数里)。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值