请记住,您可以轻松地选择性地阻止您选择的信号类型(包括 SIGALRM)中断您不想中断的阻塞操作。使用 pcntl_sigprocmask() 来保护您代码的任何部分,无论何时需要,并且不会影响其其余部分的预期信号行为。
这是一个简单的示例,说明如何屏蔽一个阻塞 sleep 操作不被中断,同时允许它发生在另一个操作旁边 - 彼此紧挨着。
<?php
$alarm = 2;
$sleep = 10;
$stamp = time();
pcntl_async_signals(TRUE);
pcntl_signal(SIGALRM, function(int $sig) use ($alarm, &$stamp) {
$late = (($now = time()) - $stamp) - $alarm;
$stamp = $now;
echo '* 闹钟信号处理程序 * 触发 '. ($late ? ($late .' 秒延迟') : '按计划') .' *'. PHP_EOL;
pcntl_alarm($alarm);
});
function get_some_sleep(int $duration, string $info) {
$start = time();
echo PHP_EOL . $duration .' 秒休眠 - '. $info . PHP_EOL;
sleep($duration);
$early = $duration - (time() - $start);
echo '休眠 '. ($early ? ('被中断。提前 '. $early .' 秒唤醒。') : '未被中断。') . PHP_EOL;
}
pcntl_alarm($alarm);
while (TRUE) {
get_some_sleep($sleep, '无保护');
pcntl_sigprocmask(SIG_BLOCK, [SIGALRM]);
get_some_sleep($sleep, '受 sigprocmask() 保护');
pcntl_sigprocmask(SIG_UNBLOCK, [SIGALRM]);
}