ページの作成や編集にはユーザ登録が必要です。
mod_perl2 における ModPerl::Registry 環境での不具合
- 投稿者: kidak
- カテゴリ: 本体
- 優先度: 重要
- 状態: 提案
- 日時: 2009年12月22日 16時37分45秒
不具合内容
下記の環境下で、print 文による Content-Type がApache に正常にわたらないことにより、Apache のエラーログに下記のような内容が記録される。
- Premature end of script headers: wiki.cgi
- wiki.cgi did not send an HTTP header
また、ページの編集後のリダイレクトページにエラーメッセージが表示されたり、リダイレクトが動作せずに HTML source が表示されたり、なぜか別のページの画像がダウンロードされたりする。
環境
- Apache 2.2.14 (prefork)
- mod_perl 2.0.4
- perl 5.8.4
- ModPerl::Registry (httpd.conf も参照のこと)
httpd.conf 抜粋
LoadModule perl_module modules/mod_perl.so <IfModule mime_module> AddHandler cgi-script .cgi </IfModule> <Directory "/var/www/html/wiki"> Options FollowSymLinks AllowOverride AuthConfig Limit Order Deny,Allow Deny from all SetEnv FSWIKI_HOME "/var/www/html/wiki" PerlSetEnv FSWIKI_HOME "/var/www/html/wiki" <IfModule mod_perl.c> <Files wiki.cgi> Options +ExecCGI SetHandler perl-script PerlOptions +ParseHeaders PerlResponseHandler ModPerl::Registry Order allow,deny Allow from all </Files> </IfModule> </Directory>
原因
おそらく二つの原因があります。
原因1
print によって Content-Type を出力する際に、$| (autoflush) の値が 0 以外であるため。この値が 0 以外のときに、Apache が正常に Content-Type を認識できない場合がある。(再現性は高いが、確実な再現方法はない)
これは mod_perl2 の bug か仕様の微妙なラインであり、mod_perl2 側での対応が見込めないと考えるため、FSWiki 側での対応を提案する
原因2
lib/Util.pm 内の send_mail において、setup.dat に設定している sendmail コマンド (/usr/lib/sendmail など) が、パイプによって起動されるため。(なぜそうなのかがわかっていませんが。。。)
これは環境依存かもしれないうえ、正しい解決法かがわかっていないので、該当者が各自での対応を期待する。(FSWiki の作者様の考え方に任せます。)
原因1 への対応方法
Content-Type を出力する際に、$|=0; にする。
パッチ
手抜きパッチのため、wiki 本体に取り込む際にはENV{'MOD_PERL'} などでの判定があってもよいかもしれません。
注意
Wiki 自体が chdir を期待するようなので、Linux/Unix の場合は Apache の MPM は prefork であるべきです。 (Windows のことはわかりません)そのため、前提は prefork MPM であること。です。
対象ファイル
すべてのファイルでの対応が必要かどうかは不明ですが、こちらで修正した標準ファイルは下記のとおりです。(いずれも上記のパッチで対応されます)
- wiki.cgi
- lib/CGI2.pm (←wiki-3_6_3_1-mod_perl_4.patch で追記)
- lib/Wiki.pm
- plugin/admin/AdminLogHandler.pm
- plugin/attach/AttachHandler.pm
- plugin/core/Source.pm
- plugin/pdf/PDFMaker.pm (←wiki-3_6_3_1-mod_perl_4.patch で追記)
- plugin/rss/RSSMaker.pm
- plugin/rss/RSSMaker10.pm
原因2 への対応方法
- setup.dat にて、"send_mail = " をブランクのままにする。
- メールを送信したい場合は、"smtp_server = " に smtp server を記入する
- (参考) port 25 以外が smtp server の場合は lib/Util.pm を以下のように直接編集する
- (default) my $smtp = Net::SMTP->new($wiki->config('smtp_server'));
- 上記を下記のように書き換える
- (参考値) my $smtp = Net::SMTP->new('172.16.1.1', Port=>'587');
注意
今件の対応は妥当性が検証されていません。(解決の実績による提案です)また、この不具合自体が kidak の環境依存の可能性もありますので、実際に下記のような不具合が起きた場合のみ実施ください。
- (前提)ページの編集時に sendmail を使ってメールを送信するように設定している。
- ページの編集直後に一瞬だけエラーが見える (Meta によるリダイレクトの場合)
- ページの編集直後に表示されるのが HTML source になる (Meta によるリダイレクトの場合)
- ページの編集直後に Location メッセージだけが表示され、リダイレクトされない (Location によるリダイレクトの場合)
コメント
- この話題では、「mod_perl が HTTP ヘッダを出力すべきか否か判断するために、FSWiki 出力の冒頭部分を見る」という動作(PerlOptions +ParseHeaders)が前提になっていると思います。その判断を正しく行わせるために、$| = 0 でなければならないわけですよね。さて、別の観点から考えると、常に mod_perl 側ではヘッダを出力しないように強制的にしてしまえばよいように思います。とみぞーノート/mod_perlハンドラを書く/HTTPレスポンスヘッダの作成によると、「Apacheにヘッダを送らせず、あなたが自分でヘッダ(non-parsed headers handlers)を送信したい場合は、$r->assbackwards メソッドを使ってください。」とあるので、この $r->assbackwards メソッドを wiki.cgi 冒頭で使ってヘッダ強制非出力にしてしまう、という解もあるのかもしれません。当方でも mod_perl 環境をインストールして試したのですが不具合自体を再現できなかったので、もし可能でしたらこちらの解も試していただけないでしょうか? (その方が、毎回 local $| = 0 しなくて済み、修正点が少なくなるので) - ぐうます (2009年12月22日 18時25分25秒)
- これを適用しても redirect/redirectURL は完全な期待通りには動いていません。いったんある程度動くようになったので、これ以上いじるのはほかの方に期待です。環境特有かもしれない旨追記しておきました。 - kidak (2009年12月24日 11時25分48秒)
- 上記では、「Content-Type を出力する際に、$| (autoflush) の値が 0 以外であることが原因」となっていますが、本当は「HTTP ヘッダを出力する際に、$| の値が 0 以外であることが原因」だったりはしないでしょうか? ログイン中の場合、各レスポンスで最初に出力される HTTP ヘッダは Set-Cookie のはずです。FSWiki の perl ソースファイル内で print "Set-Cookie: 〜" している箇所の直前にも local $| = 0 をしてみるのはいかがでしょうか。(セッション ID のクッキーの Set-Cookie: は lib/CGI2.pm で出力されます。) - ぐうます (2009年12月24日 12時54分04秒)
- あ、それよりもまず、試しに wiki.cgi の冒頭の block 内ではないところで local $| = 0 してみる方が簡単かもしれませんね。「FSWiki 自身が動作中に $| = 1 とすることはない」という仮定が成り立てば、これで FSWiki 全体に効くのではないでしょうか。 - ぐうます (2009年12月24日 13時37分54秒)
- あ、patch に含まれませんね。。。CGI2.pm の該当部分も $|=0; 対応してあります。 - kidak (2009年12月24日 14時49分18秒)
- wiki-3_6_3_1-mod_perl_2.patch を添付しました。そのほか同梱されていたライブラリ群も CPAN の最新版に置き換えてみてますが、redirectURL はダメでした。。。 - kidak (2009年12月24日 14時54分21秒)
- wiki-3_6_3_1-mod_perl_4.patch で整理しなおしました。wiki.cgi に unless($save) とか入ってるのはご愛嬌。。。 - kidak (2009年12月24日 15時17分38秒)
最終更新時間:2009年12月27日 01時11分41秒