Webサーバー


2011年2月15日

レジューム機能

途中からダウンロードを再開できるレジューム機能は、HTTP/1.1に実装されている。
Range や Content-Rangeヘッダを含むGETメソッドにて指定バイトよりダウンロードが可能となり、その際のStatus Codeは206(Partial Content)となる。これらのヘッダを受け入れるかどうかはサーバーによって異なる。

詳しくはこちら

2009年12月 6日

Segmentation faultが発生するとHTTPレスポンスが返らない

Linux+Apache2 + PHPの環境において、特定のページだけがブラウザでアクセスしても「ページが表示できません」となってしまう。

VirtualHostディレクティブで設定しているaccess_logをtail -f で監視していても対象のページだけリクエストがログに残らない。ページが表示されるときには正しくログに残っているので、書き出し先が間違っているわけでもない。

次にVirtualHostディレクティブで設定しているerror_logを見てみたが考えられるエラーは記録されていない。

その次にWiresharkでTCP通信を監視してみた。すると
(正常系)
クライアント --(SYN)--> サーバー
クライアント <--(SYN+ACK)-- サーバー
クライアント --(ACK)--> サーバー
クライアント --(ACK)--> サーバー HTTPリクエスト
クライアント <--(ACK)--> サーバー HTTPレスポンス
と続くはずが

(異常系)
クライアント --(SYN)--> サーバー
クライアント <--(SYN+ACK)-- サーバー
クライアント --(ACK)--> サーバー
クライアント --(ACK)--> サーバー HTTPリクエスト
クライアント <--(ACK)-- サーバー
クライアント <--(ACK+FIN)-- サーバー
クライアント --(ACK)--> サーバー
クライアント --(ACK+FIN)--> サーバー
で通信が終了してしまっている。

つまりHTTPレスポンスが返っていないのだ。
(このときはなぜにFINを返してしまうのだーと正直思った)

Linuxでもtcpdumpを使って解析したが、同じパケットがやり取りされており、通信経路上の問題点ではないことがわかった。

そうなるとTCPレイヤーが上位アプリケーション層にパケットを渡さなかったか、アプリケーション層が受け取ったパケットに対する応答をTCPレイヤーに返せないかのどちらかである。

/var/log/messageにはなにも記録されていなかったので、前者は考えにくく、またこの現象はPHPプログラムを入れ替えた機能から発生していることをみると、プログラムが怪しそうだったので、前のプログラムに入れ替えるとやはり問題が改善していた。

プログラムで問題のあると思われるところを修正した結果、正しくページが表示できるようになった。

これでめでたしめでたしだったが、ステータスコードが返せない理由がよくわからなかったので、ログをいろいろ調べてみた。
すると、httpd.confで設定しているerror_logをみると
[notice] child pid 21450 exit signal Segmentation fault (11)
という記録があった。

今回勉強になったのは次の3点
・Segmentation faultなどの致命的な問題が起動プログラム上で発生した場合、ApacheはログをVirtualHostディレクティブで指定したErrorLogのパスに書き出してくれない。(子プロセスが落っこちるから仕方ない?)
・また、Apacheの子プロセスが落っこちた場合にHTTPレスポンスを返せない。
・access_logを記録するのはHTTPレスポンスを返したあとなので、リクエストを受け取れたとしてもaccess_logには記録が残らない。

初めて遭遇した不可思議なこのトラブルには解決に2時間くらい要してしまった。。。