January 2026

S M T W T F S
     123
4 5678 910
11 12 1314151617
18192021222324
25262728293031

Style Credit

Expand Cut Tags

No cut tags
Wednesday, December 24th, 2003 12:05 am
Обнаружил баг в Apache/PHP.

Проявляется в том, что некоторые запросы переходят в keepalive state (т.е. ждут продолжения запроса после окончания предыдущего на том же сокете) и остаются там навечно. Таким образом, постепенно все процессы Apache попадают в это состояние, если keealive включен, а так как выйти из него у них не получается - сервер постепенно задыхается. Причём таймаут, который у апача есть для избежания таких ситуаций, не работает. Собственно, с этого всё и началось - сервер наш начал вдруг необьяснимо дохнуть, притом что ни нагрузки процессора, ни наплыва посетителей особого не наблюдалось.

По расследованию оказалось, что функция, которая должна работать по таймауту, не вызывается. А не вызывается она потому, что есть такой флаг alarms_blocked, который блокирует обработку сигналов. Когда обработка сигналов неуместна, вызывается ap_block_alarms(), которая делает ++alarms_blocked, а когда снова можно - ap_unblock_alarms(), в которой написано вот что:

--alarms_blocked;
if (alarms_blocked == 0) {
и далее обрабатываются случаи, видимо, когда в период, что сигналы были заблокированы, был сигнал и теперь пора его отработать.

Постфактум я думаю, что уже увидя этот код, я должен был заподозрить неладное. Но с первого раза я не понял, в чём дело. Запустил отладчик и посмотрел значение alarms_blocked в зависших процессах. И оно оказалось - -1, -2 и т.п. Тут до меня дошло - а что будет, если какой-то кривой код вызовет ap_unblock_alarms(), не вызывая перед этим block()? А то и будет, что с этого момента не судьба этому процессу больше принимать сигналы по таймауту - то есть судьба, но ровно тогда, когда кто-нибудь ему это _запретит_.
Завтра буду искать, кто же это такой умный этот флаг портит. То ли это в самом Apache, то ли в модуле PHP - он тоже с этими функциями играется.
Wednesday, December 24th, 2003 03:55 am (UTC)
Мне когда-то один из разработчиков ядра FreeBSD говорил, что ядро Linux работает медленнее из-за того, что разные части ядра друг другу не доверяют и перепроверяют переданные параметры.
Wednesday, December 24th, 2003 02:29 pm (UTC)
Брехня это всё. Весь кернел компилируется с оптимизацией, а это значит, что лишний код вылетает за скобки. Советую попробывать дать gcc скомпелировать код в ассемблер с -O и без и сравнить результат. Вы будете очень приятно удивлены:)))