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時間くらい要してしまった。。。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です