質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

PHP7update後、Segmentation faultが起きます。追記・PHPのGCが原因?

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 5
  • VIEW 11K+

snic518

score 37

初めて質問させていただきます。

yum updateでphp7.0.2にアップデートしました。
サーバー上のアプリケーションは、見た目上は特に不具合なく動いているのですが、ApacheのエラーログにはSegmentation faultが非常に多く記録されるようになってしまいました。

(例)
[notice] child pid 2566 exit signal Segmentation fault (11)

coreファイルを取得し、gdbを見てみたのですが、下記のような結果になりました。

(gdb)where の結果

#0  0x00007f177b70a2ff in zend_hash_str_find () from /etc/httpd/modules/libphp7.so
#1  0x00007f177b60745e in php_session_start () from /etc/httpd/modules/libphp7.so
#2  0x00007f177b60793d in ?? () from /etc/httpd/modules/libphp7.so
#3  0x00007f177b6eeaa9 in dtrace_execute_internal () from /etc/httpd/modules/libphp7.so
#4  0x00007f177b773d12 in ?? () from /etc/httpd/modules/libphp7.so
#5  0x00007f177b73bf10 in execute_ex () from /etc/httpd/modules/libphp7.so
#6  0x00007f177b6eebee in dtrace_execute_ex () from /etc/httpd/modules/libphp7.so
#7  0x00007f177b78efcb in zend_execute () from /etc/httpd/modules/libphp7.so
#8  0x00007f177b6fd553 in zend_execute_scripts () from /etc/httpd/modules/libphp7.so
#9  0x00007f177b69ef90 in php_execute_script () from /etc/httpd/modules/libphp7.so
#10 0x00007f177b792e6d in ?? () from /etc/httpd/modules/libphp7.so
#11 0x00007f1785fe7490 in ap_run_handler ()
#12 0x00007f1785fead1e in ap_invoke_handler ()
#13 0x00007f1785ff64c0 in ap_process_request ()
#14 0x00007f1785ff32a8 in ?? ()
#15 0x00007f1785feefa8 in ap_run_process_connection ()
#16 0x00007f1785ffb4f7 in ?? ()
#17 0x00007f1785ffb81a in ?? ()
#18 0x00007f1785ffbb4b in ap_mpm_run ()
#19 0x00007f1785fd2d55 in main ()

いくつか出てきたcoreファイルは、すべてこのエラーでした。
libphp7.soに問題があるように思えますが、同様なハマり方をした方、どのように解決されましたでしょうか。

エラーログの出方ですが、HTTPアクセスの量に応じてログも増えているような傾向があるのですが、いっぺんに3プロセスほどまとまって落ちたり、完全にHTTPアクセスと同期したエラーではなさそうに思えます。

[Wed Feb 03 11:45:07 2016] [notice] child pid 11648 exit signal Segmentation fault (11)
[Wed Feb 03 11:45:07 2016] [notice] child pid 11651 exit signal Segmentation fault (11)
[Wed Feb 03 11:45:07 2016] [notice] child pid 11662 exit signal Segmentation fault (11)

プロセスはhttpdで間違い無さそうなのですが、やはり普通にサイトは動作しているようで、
このエラーが発生した時にユーザーに障害が発生しているということでもなさそうです。
キャッシュ関連の動作(Opchaceなど?)が関連しているのかもと思いましたが、正体がわかりません…。

他、関連するかはわからないですが起きている事象としては、MySQLのAborted clientsが似たようなペースで増えています。
これも、PHPアップデート前は発生していませんでした。

どなたか、ご助言いただけますと幸いです。

よろしくお願いいたします。


【201602031909追記】

エラーログとプロセスを確認したところ、少し事象が見えてきたきがしたので追記です。

ある時間(2016-02-03-1825)のtopのスクリーンショットを取り、その後のエラーログを確認したところ、殆どのhttpdプロセスはこのエラーを吐いているということがわかりました。

top

これに映っているhttpdのPIDを全て調べたところ、2/3くらいはエラーログが存在しました。

# 201602031902頃のエラーログを検索
[Wed Feb 03 18:26:52 2016] [notice] child pid 21489 exit signal Segmentation fault (11)
[Wed Feb 03 18:27:41 2016] [notice] child pid 21493 exit signal Segmentation fault (11)
[Wed Feb 03 18:28:25 2016] [notice] child pid 21440 exit signal Segmentation fault (11)
[Wed Feb 03 18:27:43 2016] [notice] child pid 21366 exit signal Segmentation fault (11)
[Wed Feb 03 18:28:19 2016] [notice] child pid 21522 exit signal Segmentation fault (11)
[Wed Feb 03 18:28:22 2016] [notice] child pid 21520 exit signal Segmentation fault (11)
[Wed Feb 03 18:28:25 2016] [notice] child pid 21494 exit signal Segmentation fault (11)
[Wed Feb 03 18:28:27 2016] [notice] child pid 21257 exit signal Segmentation fault (11)
[Wed Feb 03 18:28:47 2016] [notice] child pid 21519 exit signal Segmentation fault (11)
[Wed Feb 03 18:30:15 2016] [notice] child pid 21455 exit signal Segmentation fault (11)
[Wed Feb 03 18:31:15 2016] [notice] child pid 21376 exit signal Segmentation fault (11)


↓無かったPID
21521
21444
21403
21453
21525

また、topコマンドで今生きているPIDをエラーログから探しても見つかりませんでした。(これは当たり前ですかね…)

サイトのアプリケーション動作自体は普通に動いている、サイトアクセスの増加にともなってエラーログも増える、ということを踏まえると、このエラーはhttpdプロセスが終了する時に発生しているのでは、という気がしてきました。


【20160205追記】

更に色々と調査しました。
最初の書き込み時に下記の現象について書きました。

MySQLのAborted clientsが似たようなペースで増えています。
これも、PHPアップデート前は発生していませんでした。

これの原因が判明しました。

オブログ — Statement の解放漏れには気をつけよう

スクリプトを調べたところ、いくつかMySQLのStatementをcloseしていない箇所が見つかり、それをcloseするように直したところ、Aborted cliantの増加は止まりました。

正常に動作する場合は、新しい PreparedStatement が上書きされた後に GC が上手く動作して古い PreparedStatement が解放されるのですが、GC が上手く動作しない場合は古い PreparedStatement が解放されず、データベースとの接続を保った状態のまま残ってしまいます。

この問題が発生する前ではStatementをcloseしなくてもAborted cliantが増えてなかったのが、問題発生後に顕在化したということは、上記引用にある通り、GCが上手く動作しない状態にあるのではと推察します。

  1. PHPをupdate後、GCに問題が発生し、Segmentation faultが大量発生
  2. GCが上手く動かないため、これまではよしなにされていたPHPスクリプトのStatement解放漏れが顕在化

というのが現状なのかと思います。
2に関してはもともとスクリプト側の問題ということで、それはそれで修正出来て良かったのですが、1に関しては未だに原因不明です。

思いあたる節としては、諸事情でPHPのインストールユーザーとApacheの実行ユーザーに違いがあるため、sesston_save_pathの所有者がそのままだとセッションの書き込みが出来ないために、そのディレクトリの所有者をchownしている点です。

他に所有者変更が必要なディレクトリがあるのかもしれませんが、調べても見つかりませんでした。

どなたか、ご意見いただけますと幸いです。

【20160209追記】

PHP7.0.3がリリースされていたので、アップデートしてみては、との助言をいただきました。

yum --enablerepo=remi-php70 update php php-devel php-opcache
PHP 7.0.3 (cli) (built: Feb 3 2016 11:40:05) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

アップデートは問題なく終了したのですが、サーバー再起動後、やはり継続してSegment faultは発生し続けています。
PHP本体の問題ではなかったのですかね…。

Zend OPcache がv7.0.6-devなのが少し気になりますが、もしかしてこれのverを下げたほうがいいのでしょうか。

ご意見いただけますと幸いです。

【20160209追記2】

PHPのバグフォーラムを調べたところ、PHP7.0.2で似たような状況の報告を見つけました。

こちら

「見かけは動いているけど、Segmentation faultエラーが大量に出る」という点で一致しています。
gdbの結果の内容は違うみたいですが、原因は同じなのでしょうか。

また、httpdのプロセスidを観察してみたところ、やはり終了時にSegmentation faultが発生しているので間違い無さそうでした。

topコマンドで今ある適当なpidを選び、
/proc ディレクトリにあるプロセスディレクトリを監視、
それが消去された時点でApacheエラーログを見たところ、同じpidのSegmentation faultログが出力されていることを確認しました。

他、使用しているPHPライブラリに問題がないか確かめましたが、これも無関係のようでした。

引き続き調査しようと思います。

【20160212追記】

コメントにて、php-debuginfoを入れて再度gdbをとのご意見をいただきましたので、結果を記載します。

yum --enablerepo=remi-php70 install php-debuginfo


php70-php-debuginfo-7.0.3-1.el6.remi.x86_64がインストールされました。

coreファイルをgdbで実行し、where,listをしてみた結果が以下です。

(gdb) where
#0 0x00007f177b70a2ff in zend_hash_index_find_bucket (ht=0x0,
h=13841567621774083997) at /usr/src/debug/php-7.0.3/Zend/zend_hash.c:544
#1 zend_hash_index_exists (ht=0x0, h=13841567621774083997)
at /usr/src/debug/php-7.0.3/Zend/zend_hash.c:2021
#2 0x00007f177b60745e in ?? ()
at /usr/src/debug/php-7.0.3/ext/session/session.c:1676
from /etc/httpd/modules/libphp7.so
#3 0x00007f17790174a0 in ?? ()
#4 0x00007f177bacb368 in labels.92387 () from /etc/httpd/modules/libphp7.so
#5 0x00007f17882f0410 in ?? ()
#6 0x00007f1779017030 in ?? ()
#7 0x00007f177bacb366 in labels.92387 () from /etc/httpd/modules/libphp7.so
#8 0x00007f177b60793d in zend_string_release ()
at /usr/src/debug/php-7.0.3/Zend/zend_string.h:271
#9 php_session_start () at /usr/src/debug/php-7.0.3/ext/session/session.c:1644
#10 0x0000000000000000 in ?? ()

(gdb) list
539 nIndex = h | ht->nTableMask;
540 idx = HT_HASH_EX(arData, nIndex);
541 while (idx != HT_INVALID_IDX) {
542 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
543 p = HT_HASH_TO_BUCKET_EX(arData, idx);
544 if (p->h == h && !p->key) {
545 return p;
546 }
547 idx = Z_NEXT(p->val);
548 }

zend_hash_index_find_bucketの問題なのかと思い検索してみましたが、過去この部分にバグフィックスがあったらしい(もう直ってる)ことくらいしかわかりませんでした。

ご意見いただけますと幸いです。

【20160212追記2】

文字数の制限に達してしまったので、gdb listを1個1個のframeに対して実行した結果を作成しました。

gdb list一覧

ここからもし原因がわかれば、ご助言いただけますと幸いです。

【20160215追記】

環境の問題かも、と思い、yum updateで諸々のモジュールを最新にしたり、カーネルアップデートをしたりしてみました。

カーネルバージョン
cat /proc/version
Linux version 2.6.32-358.23.2.el6.x86_64 (mockbuild@c6b9.bsys.dev.centos.org) (g cc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) ) #1 SMP Wed Oct 16 18:37:12 U TC 201320160213 kernel update

Linux version 2.6.32-573.18.1.el6.x86_64 (mockbuild@c6b8.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC) ) #1 SMP Tue Feb 9 22:46:17 UTC 2016

が、これでも改善はされませんでした。
あと残るはCentOSが6.4なのを最新にしてみるか、くらいなのですが、関係あるのかどうかは今のところわかりません…。
6.4だとPHP7で問題あるのかどうかの情報はないようです。

# cat /etc/redhat-release
CentOS release 6.4 (Final)

今これをアップデートすると、下記が入るようです。
centos-release.x86_64 6-7.e16.centos12.3

ご意見いただけますと幸いです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • katsumiy

    2016/02/10 23:48 編集

    .

    キャンセル

  • katsumiy

    2016/02/10 23:51

    debuginfo をインストール後、core を gdbで開けて、where とlist コマンドを実行してもらえますか?

    php70-php-debuginfo-7.0.3-1.el6.remi.x86_64

    キャンセル

  • snic518

    2016/02/12 09:44

    コメントありがとうございます。試してみた結果を、記事に追記しますのでご確認ください。

    キャンセル

回答 2

+4

以下のzend_string_release の延長線で落ちています。
この zend_string_release は成功すべきだと思いますので、本当の原因はわかりませんが、
session id のストリングに、<>'"\ などの許されないキャラクターが入っている場合にしか、
このコードは実行されません。パケットキャプチャして、へんなsession id が入っていないか確認してみてはどうでしょうか?

/* Finally check session id for dangerous characters
     * Security note: session id may be embedded in HTML pages.*/
    if (PS(id) && strpbrk(ZSTR_VAL(PS(id)), "\r\n\t <>'\"\\")) {
        zend_string_release(PS(id));
        PS(id) = NULL;
    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/12 20:54

    ご回答ありがとうございます。
    生成されているセッションIDをざっと確認してみました。
    しかし、英数字以外の文字列が含まれたものはありませんでした。
    更にこのzend_string_release の中に問題の発生箇所があるのでしょうか。

    引き続き調べてみますが、他に何かご助言があれば、コメントいただけますと幸いです。

    キャンセル

check解決した方法

0

長らくこちらは放っておいてしまいましたが、
結局のところ原因不明であったため、環境のリフレッシュと、そもそものPHPスクリプトの見直しのため、Web環境を引っ越しました。

結果的に、Segmentation Faultについては旧環境のように無尽蔵に出続けることは無くなりました。
色々と環境自体が変わっているので、それはそれでまた別の問題が見受けられたりしてはいますが、一旦この内容については、原因についてはわからないものの、Closeといたします。

ご協力いただいた皆様、ありがとうございました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる