Пишу, по большей части, про историю, свою жизнь и немного про программирование.

ПХП и Винда

Порядка полугода назад разговаривали с кем-то о кроссплатформенности скриптовых языков, речь и о ПХП шла, в частности. Я, памятуя о каких-то проблемах, связанных с тем, что когда-то разрабатывал на собственной машине под «Виндой», а потом переносил на «Линукс», доказывал, что по меньшей мере в ПХП всё плохо, но конкретных проблем вспомнить не мог.

А тут, на днях, нужно было продумать веб-сервис на ПХП, который именно под «Виндоуз» и работает, нужно обращаться к КОМ-объекту программы, которая только на этой платформе бывает. Сразу проблема всплыла.

По задумке внешний клиент дёргает «ручку» у сервиса, получает некий идентификатор и ждёт до поры до времени. Работа сервиса же какое-то время продолжается, тут я планировал использовать register_shutdown_function. Не тут-то было.

Функция не заработала правильно ни с «Апачем», ни с «Энжиникс», в комментариях пользователей к документации есть одинокий комментарий 2002-го года, который сообщает о проблеме:

Note that register_shutdown_function() does not work under Apache on Windows platforms. Your shutdown function will be called, but the connection will not close until the processing is complete. Zend tells me that this is due to a difference between Apache for *nix and Apache for Windows.

Похоже с тех пор ничего не изменилось. Ну хорошо, я вспомнил, что в последние ПХП входит патч php-fpm, который похожий функционал содержит — функцию fastcgi_finish_request. Оказалось, что php-fpm не работает под «Виндой».

Решили не перебирать больше решения, а сразу перейти на запуск отдельного фонового процесса. Оказалось и это не тривиально сделать. Под «Виндой» нужно это делать следующим образом:

$commandline = 'start /b тут-программа-которую-надо-запустить';
pclose(popen($commandline, 'r'));

Сплошные приключения.

11 комментариев
Николай 2012

Удобно читать «Энжиникс», вместо nginx, респектую.

MiRacLe (miracle.rpz.name) 2012

Для запуска «фоновых php-процессов» (при их разумном количестве и приемлимом времени выполнения) удобно использовать сам веб-сервер — сделать http-запрос на «рабочий» скрипт и закрыть соединение. Не надо специально следить за процессами (и их количеством), кроссплатформенно, мин нет...

Евгений Степанищев (bolknote.ru) 2012

Комментарий для miracle.rpz.name:

Может это и удобно, но в случае prefork Apache это лишний процесс веб-сервера, занятая память, меньшее количество соединений, которые он может обработать и т. п.

andr.mp 2012

offtopic: помятуя -​-​> памятуя

Евгений Степанищев (bolknote.ru) 2012

Комментарий для andr.mp:

И правда, спасибо!

Дмитрий 2012

Комментарий для Евгения Степанищева:

Женя, расскажи лучше как получить тело POST-запроса при отправке формы с multipart/form-data.

Евгений Степанищев (bolknote.ru) 2012

Комментарий для Дмитрий:

Насколько я знаю, способа сделать это только из ПХП не существует. Может вы неверно задачу поставили? Для чего вам получать сырое тело запроса в этом случае? Вы сами его парсить собираетесь? Если да, то замените этот заголовок перед ПХП, например, в веб-сервере.

Дмитрий 2012

Комментарий для Евгения Степанищева:

Я тоже это знаю, но вдруг...

Например, получить тело запроса чтобы распарсить все значения полей (имена без скобок) с одинаковыми именами.

Евгений Степанищев (bolknote.ru) 2012

Комментарий для Дмитрий:

чтобы распарсить все значения полей (имена без скобок) с одинаковыми именами.

Правильнее поправить в коде так, чтобы в ПХП они приходили в соответствии с требованиями этого языка.

Олег Горбунов 2012

Комментарий для Евгения Степанищева:

Ну, про эту «кроссплатформенность» хорошо написано у Спольски в «Дырявых абстракциях» — http://russian.joelonsoftware.com/Articles/LeakyAbstractions.html

Евгений Степанищев (bolknote.ru) 2012

Комментарий для Олег Горбунов:

Спасибо! Перечитал с удовольствием.