CakeFest 2024: The Official CakePHP Conference

pcntl_signal_dispatch

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

pcntl_signal_dispatchAppelle les gestionnaires de signaux pour chaque signal en attente

Description

pcntl_signal_dispatch(): bool

La fonction pcntl_signal_dispatch() appelle les gestionnaires de signaux installés par pcntl_signal() pour chaque signal en attente.

Liste de paramètres

Cette fonction ne contient aucun paramètre.

Valeurs de retour

Cette fonction retourne true en cas de succès ou false si une erreur survient.

Exemples

Exemple #1 Exemple avec pcntl_signal_dispatch()

<?php
echo "Installation d'un gestionnaire de signal...\n";
pcntl_signal(SIGHUP, function($signo) {
echo
"Gestionnaire de signal appelé!\n";
});

echo
"Génération d'un signal SIGHUP à moi-même...\n";
posix_kill(posix_getpid(), SIGHUP);

echo
"Envoi...\n";
pcntl_signal_dispatch();

echo
"Fait\n";

?>

Résultat de l'exemple ci-dessus est similaire à :

Installation d'un gestionnaire de signal...
Génération d'un signal SIGHUP à moi-même...
Envoi...
Gestionnaire de signal appelé!
Fait

Voir aussi

add a note

User Contributed Notes 4 notes

up
41
webmaster at ajeux dot com
14 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
0
stefanis
9 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
-2
stefanis
9 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