2016-04-25 32 views
5

Sto correndo un demone PHP con un gestore di segnale per fare una pulizia ordinato e riconfigurare senza fermarsi:Cos'è una "buona" impostazione per i tick di PHP con pcntl_signal?

declare(ticks = 5); 
function sig_handler($signo) 
{ 
    ... 
} 
pcntl_signal(SIGHUP, 'sig_handler'); 
pcntl_signal(SIGINT, 'sig_handler'); 
... 

A tick è un evento che si verifica per ogni N dichiarazioni tickable di basso livello eseguite dal parser all'interno del blocco declare ... Non tutte le istruzioni sono selezionabili. In genere, le espressioni di condizione e le espressioni di argomento non sono selezionabili.

Se dichiariamo ticks = 1 allora il segnale sarà controllato tra le maggior parte delle linee di esecuzione di codice PHP, che sembra inefficiente. Così,

  • Se dichiariamo ticks = 5, significa che abbiamo un 4 a 5 caso il gestore di segnale non sarà chiamato a tutti?
  • Come è possibile determinare un'impostazione coerente ma efficiente?
  • Cosa succede durante il blocco delle chiamate, come le query del database? Il segnale viene gettato via o elaborato quando ritorna?

(Nota a margine: The formal specs sono ancora meno specifica, in quanto questo è probabilmente interprete-dipendente.)

risposta

5

Di seguito sono i miei risultati, non posso fornire alcun riferimento alla documentazione per dimostrare le mie affermazioni. Tuttavia, ho imparato il modo in cui l'interprete PHP gestisce i tick e i segnali leggendo il codice sorgente del PHP (lo pcntl extension).

  • Se impostiamo ticks = 5, significa che abbiamo un 4 a 5 caso il gestore di segnale non sarà chiamato a tutti?

PHP è un linguaggio interpretato. I gestori di segnale PHP non vengono richiamati dal sistema operativo per gestire i segnali. L'interprete registra un gestore di segnale con il sistema operativo e mette tutti i segnali che riceve in una coda.

I segnali del sistema operativo sono asincroni. L'interprete invia i segnali ai gestori definiti da te quando è il momento più appropriato per farlo. Questo accade tra le affermazioni di basso livello

declare(ticks = 5); fa funzionare il dispatcher di segnali una volta ogni 5 dichiarazioni tickable. I segnali che arrivano durante due chiamate al dispatcher non vengono persi; vengono aggiunti alla coda ed elaborati alla prossima chiamata.

Il codice del dispatcher di segnali è piuttosto leggero; non è un grande overhead usare declare(ticks = 1).

  • Come posso determinare un ambiente coerente ma efficiente?

Dipende da cosa fa il programma. Non c'è una ricetta per questo. Prova diverse impostazioni, scegli quello che ti si addice meglio.

  • ciò che accade durante il blocco delle chiamate, come le query di database? Il segnale viene gettato via o elaborato quando ritorna?

Come detto sopra, i segnali provengono e vengono elaborati in modo asincrono dal gestore di segnale installato dall'interprete. La gestione mette solo i segnali in coda. Vengono scelti dalla coda e inviati al tuo codice quando è il momento più appropriato per l'interprete (e anche il tuo codice PHP). Niente è perso.

Per quanto riguarda il database, ho controllato solo (alcuni anni fa) con mysql. Il mio codice utilizzava pcntl_fork() per creare processi di lavoro e stava elaborando SIGCHLD per tenere traccia dell'attività dei lavoratori. Per ragioni misteriose, le query MySQL non funzionavano spesso con il messaggio "connessione persa" senza alcuna ragione apparente. Dopo un'approfondita ricerca e lettura di molta documentazione, ho scoperto che i segnali fanno in modo che le funzioni della famiglia sleep() vengano restituite anticipatamente e che il codice della libreria client mysql ritenga che la connessione sia stata persa.

La soluzione era molto semplice. Ho utilizzato pcntl_sigprocmask() per bloccare il segnale SIGCHLD prima di eseguire una query MySQL e sbloccarlo immediatamente al termine della query. Non ero interessato ad altri segnali. Lasciarli venire porterebbe alla fine del processo; perché preoccuparsi di una query MySQL fallita quando il programma stava per uscire comunque?

Non so se i segnali influenzano il funzionamento di mysqli o PDO ma penso che lo facciano. L'operazione che era interessata nel mio caso era parte della comunicazione di basso livello tra il client e il server MySQL, in profondità nello libmysql e non nell'estensione PHP.

Nel tuo caso, probabilmente devi bloccare SIGHUP (questo è il segnale che di solito viene inviato ai daemon per farli ricaricare la loro configurazione).

+0

Vorrei che la documentazione di PHP fosse così completa! Grazie mille, questo è esattamente quello che volevo sapere. –