Pyh.conf’25: a new PHP conference for the Russian-speaking community

Voting

: six plus zero?
(Example: nine)

The Note You're Voting On

kuba at valentine dot dev
2 years ago
Keep in mind that you can easily and selectively prevent signal types of your choosing (including SIGALRM) from interrupting blocking operations you don't want interrupted. Use pcntl_sigprocmask() to shield any part of your code, whenever needed and without affecting expected signal behavior for the rest of it.

Here is simple example of shielding one blocking sleep operation from being interrupted while allowing it to happen to another - right next to each other.

<?php
$alarm
= 2;
$sleep = 10;
$stamp = time();

pcntl_async_signals(TRUE);

/**
* Alarm signal handler.
*/
pcntl_signal(SIGALRM, function(int $sig) use ($alarm, &$stamp) {
$late = (($now = time()) - $stamp) - $alarm;
$stamp = $now;
echo
'* ALARM SIGNAL HANDLER * Fired '. ($late ? ($late .' seconds late') : 'on schedule') .' *'. PHP_EOL;
pcntl_alarm($alarm);
});

/**
* Sleeping function.
*/
function get_some_sleep(int $duration, string $info) {
$start = time();
echo
PHP_EOL . $duration .' seconds sleep - '. $info . PHP_EOL;
sleep($duration);
$early = $duration - (time() - $start);
echo
'Sleep was '. ($early ? ('interrupted. Woke up '. $early .' seconds early.') : 'uninterrupted.') . PHP_EOL;
}

/**
* Here we schedule first alarm.
*/
pcntl_alarm($alarm);

while (
TRUE) {
/**
* This sleep can and will be interrupted by alarm signal.
*/
get_some_sleep($sleep, 'without a shield');

/**
* Now we set our shield. From now on blocked signals will be ignored.
* Each blocked signal type that fires while shield is up is put on hold.
*/
pcntl_sigprocmask(SIG_BLOCK, [SIGALRM]);
get_some_sleep($sleep, 'protected by sigprocmask()');

/**
* Now we take off our shield. If any blocked signal fired while shield
* was up now it's handler will be executed immediately, single time.
* This is very useful behaviour because we protect what needs protecting but also
* don't miss out on anything - without being flooded thanks to "once per type" queue.
*/
pcntl_sigprocmask(SIG_UNBLOCK, [SIGALRM]);
}

<< Back to user notes page

To Top