Я пишу демон в PHP 5.6. Пока это в основном Daemon
класс с mainLoop()
метод, который имеет бесконечный цикл. В каждой итерации mainLoop выполняет серию шагов.
Мне нужно, чтобы он реализовал механизм «изящного уничтожения»: если приходит SIGINT или SIGTERM, демон должен завершить текущий шаг текущей итерации, прежде чем умереть.
Моя идея состоит в том, чтобы использовать статическую переменную Daemon::CONTINUE
TRUE по умолчанию; когда приходит сигнал SIGINT или SIGTERM, устанавливается значение FALSE.
На каждой итерации перед переходом к следующему шагу демон проверяет, self::CONTINUE
переключился на ЛОЖЬ и, если это так, он возвращается.
Я знаю, что способ сделать это состоит в том, чтобы использовать pcntl_signal
, Кажется, я могу использовать его с declare(ticks=1)
или с pcntl_signal_dispatch()
, но я не уверен в разнице.
Есть ли declare(ticks=1)
сделать процесс проверки поступления сигналов после каждого тика, тогда как pcntl_signal_dispatch()
явно проверяет сигналы только когда я это называю?
Это фрагменты двух способов, которые я описал ранее. Они оба правы? Какой я должен использовать?
Способ 1
<?php
declare(ticks=1) {
pcntl_signal(SIGINT, function($signo) {Daemon::CONTINUE = FALSE;});
pcntl_signal(SIGTERM, function($signo) {Daemon::CONTINUE = FALSE;});
}
public class Daemon {
public static $CONTINUE = TRUE;
function mainLoop() {
...
if (self::CONTINUE === FALSE)
return;
...
}
}
Способ 2
<?php
pcntl_signal(SIGINT, function($signo) {Daemon::CONTINUE = FALSE;});
pcntl_signal(SIGTERM, function($signo) {Daemon::CONTINUE = FALSE;});
public class Daemon {
public static $CONTINUE = TRUE;
function mainLoop() {
...
pcntl_signal_dispatch();
if (self::CONTINUE === FALSE)
return;
...
}
}
Спасибо за вашу поддержку.
Хорошо, после некоторого тестирования и отладки я попробовал оба решения.
Я оставлю здесь свои наблюдения на случай, если кто-то столкнется с моими проблемами.
Кажется, что путь 1 с объявить (тики = 1) не работает; Я не могу понять, почему.
способ 2 с pcntl_signal_dispatch (), напротив, кажется, работает хорошо.
После более глубокого исследования, я думаю, что путь 2 в любом случае является лучшим для моего случая.
Фактически, объявлять (tick = 1), если бы он работал, запускал pcntl_signal на каждом тике, примерно соответствующий выполнению каждой строки кода.
Это может потенциально ухудшить производительность.
Напротив, очевидно, что pcntl_signal_dispatch) просто обрабатывает ожидающие сигналы, когда он вызывается, поэтому он должен быть легче при исполнении.
Других решений пока нет …