Sto lavorando a un'applicazione che ha periodicamente chiamato processi in background. Uno di questi è stato chiamato da cron, ma sto cercando qualcosa di più robusto, quindi lo sto convertendo per funzionare sotto Supervisor. (Probabilmente funzionerà per 10 minuti, durante i quali potrà rilevare il lavoro da eseguire o inattivo. Supervisor rigenererà automaticamente un'istanza pulita.)Posso contare sul fatto che register_shutdown_function() venga chiamato su SIGTERM, se pcntl_signal() è impostato?
Dal momento che Supervisor è meglio garantire che solo un numero specificato di istanze di qualcosa sono in esecuzione in parallelo, posso farla franca con loro più a lungo. Ciò significa tuttavia che i miei processi hanno maggiori probabilità di ricevere segnali di terminazione, direttamente da kill
o perché sono stati arrestati tramite Supervisor. Sto quindi sperimentando come gestire questo in PHP.
Sembra che la soluzione di base è quella di utilizzare pcntl_signal()
in questo modo:
declare(ticks = 1);
pcntl_signal(SIGTERM, 'signalHandler');
pcntl_signal(SIGINT, 'signalHandler');
function signalHandler($signal) {
switch($signal) {
case SIGTERM:
case SIGINT:
echo "Exiting now...\n";
exit();
}
}
Tuttavia, ho diversi punti nel mio codice che potrebbe fare con un accurato trattamento di arresto. Un approccio è quello di indurre un operatore a chiamare queste varie cose, ma ciò richiederebbe un po 'di refactoring, che vorrei evitare. L'alternativa è quella di aggiungere pcntl_signal()
ovunque ne abbia bisogno, ma sfortunatamente sembra che solo un gestore possa essere installato contemporaneamente.
Tuttavia, sembra che I potrebbe essere in grado di utilizzare register_shutdown_function()
. Questo non lo fa trappola ^C
o altri sigs di terminazione sulla propria, e il manuale è molto chiaro su questo punto: non saranno eseguiti
funzioni di arresto se il processo viene ucciso con un SIGTERM o SIGKILL segnale
Ciò che sorprende è che ho trovato che se utilizzo pcntl_signal()
per fare solo un'uscita, allora i gestori di shutdown sono effettivamente chiamati. Inoltre, dal momento che uno può avere molti gestori di shutdown, questo risolve bene il mio problema - ogni classe nel mio codice che desidera gestire la terminazione con garbo può catturare e gestire il proprio spegnimento.
La mia domanda iniziale è, perché funziona? Ho provato a registrare una funzione di spegnimento senza un gestore di segnale, e questo non sembra essere chiamato, come dice il manuale. Immagino che il processo sia tenuto in vita da PHP per gestire il segnale, il che fa sì che vengano chiamati i gestori di shutdown?
Inoltre, posso fare affidamento su questo comportamento, quando il manuale lo mette in dubbio? Sto usando PHP 5.5, e non sto ancora cercando di aggiornare a PHP7. Quindi sarei interessato a sapere se funziona su 5.5 e 5.6, su una varietà di distribuzioni.
Ovviamente, se dovesse funzionare (o non funzionasse) su 7.0 e/o 7.1, sarebbe interessante anche questo - sono consapevole però che ticks will be handled differently in 7.1, quindi c'è una maggiore possibilità che questo abbia un comportamento diverso .
Mi chiedo solo perché è necessario rigenerare i processi PHP (dato che non si perde memoria in modo casuale ;-))? – bwoebi
Solo buone pratiche, @bwoebi - mi dà sicurezza che c'è sempre una nuova istanza in giro, anche se PHP e il mio sistema sono completamente privi di perdite ':-)'. – halfer
Non sono d'accordo sul fatto che sia davvero una buona pratica. Per il tuo caso d'uso va bene, ma non appena hai bisogno di un socket raggiungibile in modo permanente [TCP/unix/...] (ad es. Per scaricare informazioni dal programma live), è brutto quando è intermittente irraggiungibile. – bwoebi