カメニッキ

カメとインコと釣りの人です

PHPがsegmentation faultで死ぬ原因を追跡する

発端

WordPressで構築されたサイトで 502 Proxy Error が出る、という問題が発生した。

[LB] -> [Reverse proxy] -> [Webサーバ] という構成のため、ユーザへ返るステータスコードReverse proxy が吐いてる。
ここが 502 Proxy Error となるのは、プロキシした先の Webサーバhttpdプロセスが異常終了してしまっている事が原因だった。

※ちなみに今回PHPのセグフォでhttpdが死んでいるのは、dsoだったため。httpdから生えたcgiだった場合、cgiのセグフォをhttpdが検知できるので、恐らく500エラーを返すことになる

なぜ異常終了しているかを調べた(未解決)


  • httpdのエラーログを見ると、プロセスがセグフォで死んでいることがわかる。
[Wed Nov 30 11:53:51.240210 2016] [core:notice] [pid 16547] AH00052: child pid 18079 exit signal Segmentation fault (11)
  • straceでセグフォで死ぬプログラムをみてみると brk システムコールを呼び続けて最後に死んでた
brk(0x5631000)                          = 0x5631000
brk(0x5671000)                          = 0x5671000
brk(0x56b1000)                          = 0x56b1000
brk(0x56f1000)                          = 0x56f1000
brk(0x5731000)                          = 0x5731000
brk(0x5771000)                          = 0x5771000
brk(0x57b1000)                          = 0x57b1000
brk(0x57f1000)                          = 0x57f1000
brk(0x5831000)                          = 0x5831000
brk(0x5871000)                          = 0x5871000
brk(0x58b1000)                          = 0x58b1000
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++

brkシステムコール直前 wp-content/cache/object/ とキャッシュを触っており、キャッシュ関連のプラグインが怪しいと目星がついたので、試しにそのプラグインを無効化すると、本問題は発生しなくなった。
プラグイン無効化で終わり、でもいいが、なぜセグフォするのかもう少し調査
- 次にcore dumpを吐かせた

# coreファイルのサイズ制限を外す
$ ulimit -c unlimited
# 確認
$ ulimit -a | grep core
# 問題のコードを実行する
# カレントディレクトリにcoreがはかれる
$ ls -l core.19380
# fileコマンドで何のプログラムでセグフォしたcoreかみれる
$ file core.19380
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, from '/usr/local/php/bin/php-cgi sample.php'
# gdbで解析
$ gdb /usr/local/php/bin/php-cgi -c core.19380
()
Core was generated by `/usr/local/php/bin/php-cgi sample.php'.
Program terminated with signal 11, Segmentation fault.
#0  zend_parse_arg (arg_num=1, arg=0x5e4a6b8, va=0x7ffdbf6cd110, spec=0x7ffdbf6cd0c8, quiet=0, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_API.c:686
686 /tmp/php-build/source/5.6.21/Zend/zend_API.c: そのようなファイルやディレクトリはありません.
    in /tmp/php-build/source/5.6.21/Zend/zend_API.c
(略)
(gdb) bt
#0  zend_parse_arg (arg_num=1, arg=0x5e4a6b8, va=0x7ffdbf6cd110, spec=0x7ffdbf6cd0c8, quiet=0, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_API.c:686
#1  0x000000000089dec3 in zend_parse_va_args (num_args=<value optimized out>, type_spec=0xa2b863 "s", va=0x7ffdbf6cd110,
    flags=<value optimized out>, tsrm_ls=0x1b350c0) at /tmp/php-build/source/5.6.21/Zend/zend_API.c:873
#2  0x000000000089e7d6 in zend_parse_parameters (num_args=1, tsrm_ls=0x1b350c0, type_spec=<value optimized out>)
    at /tmp/php-build/source/5.6.21/Zend/zend_API.c:924
#3  0x00000000008a8464 in zif_defined (ht=<value optimized out>, return_value=0x5dff408, return_value_ptr=<value optimized out>,
    this_ptr=<value optimized out>, return_value_used=<value optimized out>, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_builtin_functions.c:735
#4  0x000000000091bf93 in zend_do_fcall_common_helper_SPEC (execute_data=<value optimized out>, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_vm_execute.h:558
#5  0x0000000000909c4b in execute_ex (execute_data=0x5e4a610, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_vm_execute.h:363
#6  0x000000000091c44e in zend_do_fcall_common_helper_SPEC (execute_data=<value optimized out>, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_vm_execute.h:592
#7  0x0000000000909c4b in execute_ex (execute_data=0x5e4a3d0, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_vm_execute.h:363
#8  0x000000000091c44e in zend_do_fcall_common_helper_SPEC (execute_data=<value optimized out>, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_vm_execute.h:592
#9  0x0000000000909c4b in execute_ex (execute_data=0x5e49b38, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_vm_execute.h:363
#10 0x000000000091c44e in zend_do_fcall_common_helper_SPEC (execute_data=<value optimized out>, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_vm_execute.h:592
#11 0x0000000000909c4b in execute_ex (execute_data=0x5e499d0, tsrm_ls=0x1b350c0)
    at /tmp/php-build/source/5.6.21/Zend/zend_vm_execute.h:363
(略)

Zend/zend_vm_execute.h:363行目Zend/zend_vm_execute.h:592行目 が無限につづいていた。
なんでこうなるのかよくわかってない。Zendのバグなんじゃないの?とか思って眺めてた。
また、上記の問題は thread safe版 の場合。試しに同じconfigureオプションで作った non thread safe版 を使用して同じプログラムを実行させると、セグフォはおきなかった。
その代わりに brk システムコールを無限に実行し続けて memory_limit の値に引っかかってた。
試しに1GBほど割り当てても同様に全て食いつぶしてメモリ不足になってたので、やっぱりZendのバグなんじゃないの?とか思ってる。
ここからどうすれば根本的な原因(もしあるならバグの箇所)までたどり着けるのか、調べ方がわからない。勉強しようと思った

追記: 原因と思われるもの

tapira.hatenablog.com