Я запускаю демон PHP с обработчиком сигнала для упорядоченной очистки и перенастройки без остановки:
declare(ticks = 5);
function sig_handler($signo)
{
...
}
pcntl_signal(SIGHUP, 'sig_handler');
pcntl_signal(SIGINT, 'sig_handler');
...
Галочка это событие, которое происходит для каждого N низкоуровневых помеченных операторов, выполняемых синтаксическим анализатором в блоке объявления … Не все пометки являются помеченными. Как правило, условные выражения и выражения аргумента не помечаются галочкой.
Если мы объявим ticks = 1
тогда сигнал будет проверяться между большинством строк исполняемого кода PHP, что кажется неэффективным. Так,
ticks = 5
Означает ли это, что у нас есть 4 из 5 шансов, что обработчик сигнала не будет вызван вообще?(Примечание: Формальные характеристики еще менее конкретны, так как это, вероятно, зависит от переводчика.)
Ниже приведены мои выводы, я не могу предоставить вам какую-либо ссылку на документацию, подтверждающую мои заявления. Однако я узнал, как интерпретатор PHP обрабатывает тики и сигналы, прочитав исходный код PHP ( pcntl
расширение).
- Если мы установим
ticks = 5
Означает ли это, что у нас есть 4 из 5 шансов, что обработчик сигнала не будет вызван вообще?
PHP — это интерпретируемый язык. Ваши обработчики сигналов PHP не вызываются ОС для обработки сигналов. Интерпретатор регистрирует обработчик сигналов в ОС и помещает все полученные сигналы в очередь.
Сигналы ОС поступают асинхронно. Интерпретатор отправляет сигналы определенным вами обработчикам, когда это наиболее подходящее время для этого. Это происходит между отметками низкого уровня.
declare(ticks = 5);
заставляет диспетчер сигналов запускаться один раз каждые 5 отмеченных операторов. Сигналы, поступающие во время двух звонков диспетчеру, не теряются; они добавляются в очередь и обрабатываются при следующем вызове.
Код диспетчера сигналов довольно легкий; это не большие накладные расходы для использования declare(ticks = 1)
,
- Как я могу определить последовательную, но эффективную настройку?
Это зависит от того, что делает ваша программа. Нет рецепта для этого. Попробуйте разные настройки, выберите ту, которая подходит вам больше всего.
- Что происходит во время блокировки вызовов, например запросов к базе данных? Сигнал выбрасывается или обрабатывается, когда он возвращается?
Как я уже говорил выше, сигналы поступают и обрабатываются асинхронно обработчиком сигналов, установленным интерпретатором. Обработка только помещает сигналы в очередь. Они выбираются из очереди и отправляются в ваш код, когда это наиболее подходящий момент для интерпретатора (и вашего PHP-кода тоже). Ничего не потеряно.
Что касается базы данных, я проверил (несколько лет назад) с mysql
, Мой код использовался pcntl_fork()
создавать рабочие процессы и обрабатывал SIGCHLD
отслеживать активность работников. По таинственным причинам он часто не выполнялся на запросах MySQL с сообщением «соединение потеряно» без видимой причины. После тщательного изучения и прочтения большого количества документации я обнаружил, что сигналы выполняют функции sleep()
семья возвращается рано, и это делает кодекс mysql
Клиентская библиотека считает, что соединение было потеряно.
Решение было очень простым. я использовал pcntl_sigprocmask()
заблокировать SIGCHLD
сигнал перед выполнением запроса MySQL и разблокировать его сразу после завершения запроса. Меня не интересовали другие сигналы. Позволить им прийти приведет к прекращению процесса; зачем беспокоиться о неудачном запросе MySQL, когда программа все равно должна была выйти?
Я не знаю, влияют ли сигналы на работу mysqli
или же PDO
но я думаю, что они делают. Операция, которая была затронута в моем случае, была частью низкоуровневой связи между клиентом и сервером MySQL, глубоко в libmysql
а не в расширении PHP.
В вашем случае вам, вероятно, нужно заблокировать SIGHUP
(это сигнал, который обычно посылается демонам, чтобы заставить их заново загрузить свою конфигурацию).
Других решений пока нет …