Ошибка автообновления PHP после ошибки в памяти

Это может быть лучше подходит для отказа сервера, но я подумал, что сначала спрошу здесь.

У нас есть файл, который добавляется к каждому файлу PHP на наших серверах, используя auto-prepend, который содержит класс под названием Bootstrap, который мы используем для автозагрузки, обнаружения среды и т.д. Все это работает нормально.

Однако, когда есть ошибка "OUT OF MEMORY", непосредственно предшествующая (т.е. менее секунды или даже в то же время) запрос на другой файл на том же сервере, происходит одна из трех вещей:

  • Наш код для проверки if(class_exists('Bootstrap'), который мы использовали для обертывания определения класса, когда мы впервые получили эту ошибку, возвращает true, что означает, что класс уже был объявлен, несмотря на то, что это файл автопредложения.

  • Мы получаем ошибку "not not redeclare class Bootstrap" из нашего автоматически добавленного файла, а это означает, что class_exists('Bootstrap') возвращен false, но он каким-то образом был объявлен.

  • Файл не добавляется вообще, что приводит к одноразовой фатальной ошибке для файлов, которые зависят от нее.

Мы могли бы, конечно, попытаться устранить проблемы с памятью, поскольку они, похоже, вызывают другие ошибки, но по разным причинам они не могут быть исправлены в нашей установке или очень трудно исправить. Но, кроме того, мне кажется, что это ошибка в PHP с какой-то утечкой памяти, вызывающей проблемы с директивой auto-prepend.

Это больше любопытства, чем что-либо, поскольку это редко случается (может быть, раз в неделю на наших серверах с высоким трафиком). Но я хотел бы знать, почему это происходит, и что мы можем сделать, чтобы исправить это?

Мы запускаем FreeBSD 9.2 с PHP 5.4.19.

EDIT: несколько вещей, которые мы заметили, пытаясь исправить это за последние несколько месяцев:

  • Кажется, это происходит только на наших защищенных серверах. Проблемы с отсутствием памяти в основном на наших защищенных серверах (обычно из наших собственных сотрудников, пытающихся загрузить слишком много данных), поэтому это может быть просто совпадение, но заслуживает внимания

  • Дамп get_declared_classes, когда у нас есть эта проблема, содержит классы, которые не используются на странице, вызывающей ошибку. Например, вывод $_SERVER говорит, что человек находится на xyz.com, но один из объявленных классов используется только на abc.com, из которого обычно возникают проблемы с памятью.

  • Все это заставляет меня поверить, что PHP не делает правильную сборку мусора в конце цикла после получения ошибки из памяти, что приводит к тому, что класс Bootstrap должен быть полностью или частично в памяти на следующий запрос страницы, если он достаточно скоро после ошибки. Я недостаточно разбираюсь в сборке мусора PHP, чтобы на самом деле воздействовать на это, но я думаю, что это, скорее всего, проблема.

Ответ 1

Даже если class_exists возвращает false, он никогда не вернет true, если существует интерфейс с таким же именем. Однако вы не можете объявить интерфейс и класс с тем же именем.

Попробуйте запустить class_exists('Bootstrap') && interface_exists('Bootstrap'), чтобы убедиться, что вы не обновляете его.