|
|
ru.cgi.perl- RU.CGI.PERL ------------------------------------------------------------------ From : Andrey Sapozhnikov 2:5020/400 25 Jun 2004 18:08:06 To : Alexander V. Gaiduk Subject : Re: mod_perl - глюк? -------------------------------------------------------------------------------- Alexander V. Gaiduk пишет: > стал ковырять дальше по исходникам Apache::ASP дополз до BinaryRead... > там они просто читают из закэшированного буфера: $r->read($data, $length); > получаем 7.5 кило ! > > это же под виндой читает ВСЁ !!! > > дальше стал исследовать саму отправку данных методом POST - его отличия > линуховой и виндовой реализации mod_perl. > > нарисовал простейший скриптик, где читаю: > read(STDIN, $data, $ENV{'CONTENT_LENGTH'}); > под виндой - все читает, под линухом 7.5 кило! > > выяснилось, что если читать в цикле: > while (read(STDIN, $buf, $ENV{'CONTENT_LENGTH'})>0) {$data .= $buf;} > то и в виндозе и в линухе читается всё !!! > > причем при детальном исследовании оказалось, что в виндозе все данные > сразу помещаются в буфер чтения STDIN в mod_perl, а в линухе > буфер чтения ограничен 8000 байтами, но тем не менее все данные от туда > тоже можно вычитать (читать - пока читаются)... > > пришлось такой циклик воткнуть в Apache::ASP::Request > в функцию BinaryRead - после этого все поехало прально. > > Скажите, почему такое разное поведение mod_perl в линухе и в вындосе? Различное поведение обусловлено совершенно разными системными вызовами чтения файла/потока. Дело в том, что многие программисты почему-то опускают тот факт, что системный вызов read(2) в unix вовсе не обязан считать столько байт, сколько его попросили. Ситуация когда считано меньше запрошенного называется "short read" или "partial read". Почему-то большинство программистов склонны считать, что "partial read" возникает только при неблокирующем чтении (тут все логически понятно - прочитали сколько смогли, ждать не велено), при достижении конца файла (прочитали сколько осталось, больше читать нечего), и при чтении из терминальных устройств (там вообще сложная песня - количество считанных байт зависит от целого ряда параметров установленных через интерфейс termio или termios). Однако POSIX.1 (ISO/IEC 9945-1:1990: section 6.4.1.2, lines 125-128) явно описывает "partial read" который возникает при получении сигнала процессом. В этом случае, если не было считано ни одного байта read(2) должен вернуть -1, [EINTR], иначе - количество считанных байт. Учитывая то, что в программах сложнее hello_world.c предсказать моменты прихода сигналов зачастую весьма трудно, никогда не следует закладываться на то, что read вернет весь запрошенный объем данных. Так что поведение Вашего примера с read(STDIN, $data, ... вполне закономерно и допустимо (описание функции read не гарантирует полного чтения). Так же закономерно и допустимо поведение функции BinaryRead в модуле Apache::ASP::Request, поскольку она, в отличие от Вашего примера, использует метод read принадлежащий классу Apache: perldoc Apache: ... $r->read($buf, $bytes_to_read, [$offset]) This method is used to read data from the client, looping until it gets all of $bytes_to_read or a timeout happens. An offset may be specified to place the read data at some other place than the beginning of the string. In addition, this method sets a timeout before reading with "$r->soft_timeout". ... Как мы видим, Apache явно обещал читать пока не вычитает все, либо не случится таймаут. А теперь глядим в документацию к mod_perl2: http://perl.apache.org/docs/2.0/api/Apache/RequestIO.html#C_read_ : Read data from the client. $read_count = $r->read($buffer, $len, $offset); META: same as CORE::read, minus the filehandle argument * obj: $r (Apache::RequestRec) * arg1: $buffer (scalar) * arg2: $len (scalar) * arg3: $offset (number) * ret: $read_count (number) How many characters were actually read Поведение существенным образом изменилось. Теперь никто уже не обещает вычитать все. Обеспечивать совместимость mod_perl2 с mod_perl задача модуля Apache2/Apache/compat.pm, однако никто не обещал 100% совместимости. В заключение - 3 основных вопроса русской интеллигенции: Q. Кто виноват? A. с одной стороны никто не виноват. С другой стороны - все в равной степени уроды. Авторы некоторых модулей apache (не путать с mod_perl и Apache.pm) подменяют сокет пайпом (AFAIK mod_gzip так поступал для реализации компрессии на лету). Авторы mod_perl2 не обеспечивают 100% совместимости. Авторы Apache::ASP либо до сих не портировались под mod_perl2... Вероятно и авторы самого apache тоже где-то облажались (обоснование опущено). Q. Что делать? А. Логичнее всего поправить либо Apache::compat либо Apache::ASP. Q. Кто бежит за "Клинским"? A. ... -- Андрей --- ifmail v.2.15dev5.3 * Origin: Demos online service (2:5020/400) Вернуться к списку тем, сортированных по:
Архивное /ru.cgi.perl/6577ef49a68a.html, оценка из 5, голосов 10
|