Pracuję nad aplikacją, która okresowo nazywa procesy w tle. Jeden z nich został wywołany przez crona, ale szukam czegoś solidniejszego, więc zamieniam go, by działał pod nadzorem. (Prawdopodobnie uruchomi się na 10 minut, w czasie których może wykryć pracę do wykonania lub bezczynnie. Po jej zakończeniu przełożony automatycznie odradzi czystą instancję.)Czy mogę polegać na funkcji register_shutdown_function() na SIGTERM, jeśli skonfigurowano pcntl_signal()?
Ponieważ inspektor lepiej jest zapewnić, że tylko podana liczba instancji coś działa równolegle, mogę uciec z uruchomieniem ich dłużej. Oznacza to jednak, że moje procesy są bardziej skłonne do odbierania sygnałów końcowych, albo bezpośrednio od kill
, albo dlatego, że zostały zatrzymane przez Supervisora. Dlatego eksperymentuję z tym, jak sobie z tym poradzić w PHP.
Wygląda podstawowym rozwiązaniem jest użycie pcntl_signal()
tak:
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();
}
}
Mam jednak kilka punktów w moim kodu, który może zrobić z ostrożne obchodzenie zamykania. Jednym podejściem jest sprawienie, aby jeden przewodnik nazwał te różne rzeczy, ale wymagałoby to trochę refaktoryzacji, której chciałbym uniknąć. Alternatywą jest dodanie pcntl_signal()
wszędzie tam, gdzie jest to potrzebne, ale niestety wydaje się, że tylko jeden program obsługi może zostać zainstalowany na raz.
Jednak wygląda na to, że mogę być w stanie użyć register_shutdown_function()
. To nie pułapka ^C
lub inne sigs terminacji na własną rękę, a instrukcja jest jasne w tej kwestii:
funkcje wyłączania nie zostaną wykonane, jeśli proces zostanie zabity z SIGTERM lub SIGKILL sygnału
Co jest zaskakujące jest to, że znalazłem, że jeśli zatrudniam pcntl_signal()
do zrobienia wyjścia, to procedury obsługi zamykania są rzeczywiście wywoływane. Ponadto, ponieważ można mieć wiele programów obsługi zamykania, to rozwiązuje to mój problem - każda klasa w moim kodzie, która chce z wdziękiem obsługiwać zakończenie, może przechwytywać i zarządzać własnym zamykaniem.
Moje pierwsze pytanie brzmi: dlaczego to działa? Próbowałem zarejestrować funkcję wyłączania bez obsługi sygnału, a to nie wydaje się być wywołane, jak mówi instrukcja. Domyślam się, że proces jest utrzymywany przy życiu przez PHP w celu obsługi sygnału, który powoduje wywołanie procedur obsługi shutdown?
Czy mogę polegać na tym zachowaniu, gdy podręcznik rzuca w to wątpliwość? Używam PHP 5.5 i nie chcę jeszcze uaktualnić do PHP7. Byłbym zainteresowany, czy to działa w wersjach 5.5 i 5.6, w różnych dystrybucjach.
Oczywiście, jeśli byłoby (lub nie byłoby) działa na 7.0 i/lub 7.1, to byłoby również interesujące - wiem jednak, że ticks will be handled differently w 7.1, więc istnieje większe prawdopodobieństwo, że ma to inne zachowanie .
Zastanawiam się, po co właściwie odradzać się procesy PHP (biorąc pod uwagę, że nie losowo wyciekujesz pamięci ;-))? – bwoebi
Po prostu dobra praktyka naprawdę, @bwoebi - daje mi pewność, że zawsze jest świeża instancja, nawet jeśli PHP i mój system są całkowicie wolne od wycieków ':-)'. – halfer
Nie zgadzam się, że to naprawdę dobra praktyka. Dla twojego przypadku użycia może to być w porządku, ale gdy tylko będziesz potrzebował dostępnego na stałe gniazda [TCP/unix/...] (np. Do zrzucania informacji z programu na żywo), jest źle, gdy jest nieoczekiwanie niedostępny. – bwoebi