«Сломанный канал» E_NOTICE во время завершения работы PHP, устаревшие данные в закрытом сокете?

#php #php-7

#php #php-7

Вопрос:

Приложение PHP 7.2 с базой данных MySQL. Через set_error_handler установлен пользовательский обработчик ошибок. На сайте prod время от времени он получает уведомление E_NOTICE со следующей строкой ошибки:

Неизвестно: ошибка отправки 5 байтов с ошибкой errno = 32 Сломанный канал

Файл:Строка уведомления неизвестна:0.

Нет ошибки более высокого уровня, с которой это можно было бы связать. Также нет файла / строки. debug_backtrace() Пусто. Я знаю название сценария запуска для этих случаев (это PHP-скрипт командной строки с запланированным запуском CRON), но это почти ничего мне не дает.

Я видел похожие ошибки в операциях MySQL, когда сервер отключался после тайм-аута (ошибка MySQL 2006), но в этих случаях также была бы ошибка от query() или ping() . В данном случае это не так.

Ошибка выглядит как ошибка сокета; кроме MySQL, этот скрипт использует cURL для доступа к конечной точке REST. Но я не вижу ошибок cURL.

Есть идеи, как я могу отследить это до нарушающей строки, если не считать старой printf отладки?

РЕДАКТИРОВАТЬ: я отследил это до обработчика ошибок, который использует PHPMailer для отправки электронной почты через SMTP. Эта библиотека использует сокеты, поэтому ссылка на streams/xp_socket.c находится на чем-то.

ОДНАКО уведомление появляется после возврата PHPMailer::send() функции во время (или после) вызова exit() . Похоже, что есть некоторые неотправленные данные из операций сокета, которые PHP сбрасывает во время завершения работы и завершаются сбоем. Однако единственный сокет, который я вижу, закрыт во время уничтожения объекта PHPMailer.

Может ли быть какое-то устаревшее состояние в закрытом сокете?

Комментарии:

1. Единственное появление этого сообщения об ошибке находится в php_sockop_write() of main/streams/xp_socket.c , которое, я не думаю, что какой-либо драйвер mysql использует.

2. Возможно , эти уведомления были перемежены ошибками «MySQL ушел», не связанными. Трудно сказать, без указания местоположения ошибки.

3. Местоположение Неизвестно: 0 обычно указывает на ошибки запуска. Но это не имеет смысла, когда оно было зафиксировано в обработчике ошибок во время выполнения. В любом случае, громоздкий способ расследования: raise (SIGABRT); исправлено в обработчике ошибок streams, затем gdb в coredump для проверки стека вызовов. Вероятно, это будет что-то скучное…

4. Хм, я вижу, будет ли coredump там, где я могу его видеть. Это общий prod-сервер, который я не запускаю.

5. Это не ошибка запуска, это ошибка завершения работы. Какая-то очистка устаревшего состояния (но не глобальный деструктор объектов PHP).