PHP Conference Nagoya 2025

pcntl_signal_dispatch

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

pcntl_signal_dispatchВызывает обработчики для ожидающих сигналов

Описание

pcntl_signal_dispatch(): bool

Функция pcntl_signal_dispatch() вызывает обработчики сигналов, установленные функцией pcntl_signal(), для каждого ожидающего сигнала.

Список параметров

У этой функции нет параметров.

Возвращаемые значения

Функция возвращает true в случае успешного выполнения или false, если возникла ошибка.

Примеры

Пример #1 Пример использования pcntl_signal_dispatch():

<?php
echo "Установка обработчика сигнала SIGHUP...\n";
pcntl_signal(SIGHUP, function($signo) {
echo
"Вызван обработчик сигнала SIGHUP\n";
});

echo
"Посылаем сигнал SIGHUP самому себе...\n";
posix_kill(posix_getpid(), SIGHUP);

echo
"Отравка всех сигналов...\n";
pcntl_signal_dispatch();

echo
"Завершено.\n";

?>

Вывод приведённого примера будет похож на:

Установка обработчика сигнала SIGHUP...
Посылаем сигнал SIGHUP самому себе...
Отравка всех сигналов...
Вызван обработчик сигнала SIGHUP
Завершено.

Смотрите также

Добавить

Примечания пользователей 4 notes

up
38
webmaster at ajeux dot com
15 years ago
If you are running PHP as CLI and as a "daemon" (i.e. in a loop), this function must be called in each loop to check if new signals are waiting dispatching.
up
9
me at subsonic dot cz
10 years ago
Note that calling pcntl_signal_dispatch() from within a signal handler invoked by a previous pcntl_signal_dispatch() will not trigger handlers for any new pending signals. This means that if you write a CLI daemon which forks off child processes in response to a signal, then those child processes won't be able to respond to signals. This gave me a headache for a while as pcntl_signal_dispatch() doesn't raise any errors when this occurs. One solution is to set a flag within the signal handler and react upon it (by forking off the needed child processes) elsewhere in the parent process's main loop.
up
1
stefanis
10 years ago
As noted by "me at subsonic dot net" calling pcntl_signal_dispatch() from within a signal handler invoked by a previous pcntl_signal_dispatch() will not trigger handlers for any new pending signals. This seems to be true even if you pcntl_exec() a new PHP processor to execute an entirely different script.

The solution seems to be to explicitly call pcntl_signal_dispatch()inside a ticks_handler() . And use sig_handler(int) as a push function to a queue. Immediately following the call to dispatch in the ticks_handler, pop your queue doing what you would have done in the signal_handler until the queue is empty.
up
-1
stefanis
10 years ago
Well I misspoke before. It is not enough to process signals outside of the signal handler. They must be processed outside of the tick handler (explicit or implied). So...

Register a tick handler that calls pcntl_signal_dispatch();
In the signal handler, enqueue your signal;
In the main loop of your script, process your signals;

<?php
declare(ticks=1);
global
$sig_queue;
global
$use_queue;
$sig_queue = array();
$use_queue = true; // set to false to do it the old way

function tick_handler()
{
pcntl_signal_dispatch();
}

function
sig_handler($sig)
{
global
$sig_queue;
global
$use_queue;

if(isset(
$use_queue) && $use_queue)
{
$sig_queue[] = $sig;
}
else
{
sig_helper($sig);
}
}

function
sig_helper($sig)
{
switch(
$sig)
{
case
SIGHUP:
$pid = pcntl_fork();
if(
$pid) print("forked $pid\n");
break;

default:
print(
"unhandled sig: $sig\n");
}
}

pcntl_signal(SIGHUP, "sig_handler");

while(
true)
{
if(
$use_queue) foreach($sig_queue as $idx=>$sig)
{
sig_helper($sig);
unset(
$sig_queue[$idx]);
}
sleep(1);
}
?>
To Top