原因と対応方法
昨日(2019-01-24)時点で、最新の php 7.3.1
を用いて、 xdebug
と opcache
を組み合わせて開発環境を作ろうとした、 502 Bad Gateway
がたまに発生し、 phpfpm のログを確認すると exited on signal 11 (SIGSEGV)
が発生していた。
さて、どう対応するかな…と Twitter でつぶやいたところ、 Derick Rethans san から mention を頂いた!
There is a bug in OPcache that conflicts with Xdebug (and causes crashes). This is fixed in GIT, and will be released as part of PHP 7.3.2.
— Derick Rethans (@derickr) 2019年1月24日
続けて、原因と回避策まで!
https://t.co/kwVyr00BR7 is the bug, and https://t.co/YeZZ5U8dTL has a workaround
— Derick Rethans (@derickr) 2019年1月24日
Derick Rethans san. Thank you for the information!
というわけで、上記に書かれていることを実行すればとりあえず大丈夫です。
php 7.3.2
になったら、 https://github.com/php/php-src/commit/325a1139744413420a62d3006c04914587628810 が反映されるので、この問題は生じなくなると思いますよ。
もうちょっと細かく経緯と対応方法
昨日(2019-01-24)時点の Docker hub 上の php:7.3-fpm-alpine3.8
をベースに PHP 7.3 + xdebug + opcache
の開発環境を作ろうとした。
とりあえず、以下のような Dockerfile
を用意して、 docker-compose build
して docker-compose up
してみた。
FROM php:7.3-fpm-alpine3.8
RUN apk update \
&& apk upgrade \
&& apk add --no-cache --virtual .gd-deps \
g++ \
make \
autoconf \
&& pecl update-channels \
&& docker-php-ext-install \
opcache \
&& pecl install xdebug-2.7.0beta1 \
&& rm -rf /tmp/pear ~/.pearrc \
&& docker-php-ext-enable xdebug
# ホントはもっと色々書いてるのですが省略しました。
※ 2019-01-28 追記 @tomoyamachi さんのコメント を参考に echo 'zend_extension=xdebug.so' > /usr/local/etc/php/conf.d/xdebug.ini
から docker-php-ext-enable xdebug
に変更。
なお、 php 7.3 で xdebug を使うには、現状 xdebug-2.7.0beta1
を pecl から install する必要がある。(https://xdebug.org/ の Announcements や https://xdebug.org/updates.php 等を参照のこと: 最初は普通に pecl install xdebug
って書いててダメだった。ちゃんとドキュメント見るべき…)
※ phpfpm の前に nginx がいる構成なのですが、 nginx 用の Dockerfile は省略してます。
build も up も成功した!
で、ブラウザから、見てみるとどうやら動いてるっぽい!
と、思ったのもつかの間…
設定値が正しく反映されているか phpinfo()
で、ざっと目視確認しようとファイルを書き換えてリロードしたところ、502 Bad Gateway
! phpfpm が出力している stderr には exited on signal 11 (SIGSEGV)
!
え?
再度リロード。
…
普通に表示される。。。え?
再度リード。。
502 Bad Gateway
! exited on signal 11 (SIGSEGV)
! えぇぇ!!!!
(試しにその後も何度かリロードしたら再現したりしなかったりを繰り返した。)
となって、あーこれ core dump かよ。。 docker で core dump かよー。。
でも、タイミング次第ってことは多分、 opcache かなぁ。
というわけで、とりあえず、 opcache を Off にしてみることに。
$ docker-compose exec phpfpm sh
/var/www/app # vi /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
;zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20180731/opcache.so
/var/www/app # kill -USR2 1
docker-compose exec
で稼働中の phpfpm コンテナに入って、 sh を起動し、
対象のファイルを ;zend_extension=(略)
の様にコメントアウトして、
kill -USR2 1
にて、container 内から phpfpm を再起動。 https://stackoverflow.com/questions/37806188/how-to-restart-php-fpm-inside-a-docker-container
で、ブラウザからリロード確認すると、、
見事に 502 Bad Gateway
と exited on signal 11 (SIGSEGV)
が消えてなくなりました。
ここで、とりあえず opcache が怪しそうだな、とアタリをつけたのですが、 xdebug も気になります。
特に php 7.3 はリリースしてから日が浅く、 7.3 用の xdebug である 2.7.0beta1 は名前が指し通り、まだ beta 版。
もしかしたら、こっちも怪しいかも?と思い、さっきと逆の手順で opcache を有効にした後、以下の手順で xdebug を無効にしてみました。
/var/www/app # vi /usr/local/etc/php/conf.d/xdebug.ini
;zend_extension=xdebug.so
/var/www/app # kill -USR2 1
で、こちらも見事に 502 Bad Gateway
と exited on signal 11 (SIGSEGV)
が消えてなくなりました。
ということで、 opcache
+ Xdebug 2.7.0beta1
+ php:7.3-fpm-alpine3.8
の組み合わせによって何らかのバグを踏んでいる可能性が高そうだと考えました。
※(opcache
or xdebug
) + php:7.3-fpm-alpine3.8
なら問題ない。
で、冒頭の Tweet をしたところ、サクッと Derick Rethans san から mention を頂いた次第です。
ありがたい。
その後、 php:7.3-fpm-alpine3.8
の今の php version を確認すべく以下のコマンドで 7.3.1 であることを確認し、
$ docker-compose exec phpfpm php -v
PHP 7.3.1 (cli) (built: Jan 11 2019 00:59:32) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.1, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.3.1, Copyright (c) 1999-2018, by Zend Technologies
with Xdebug v2.7.0beta1, Copyright (c) 2002-2018, by Derick Rethans
教えていただいた workaround に従い Dockerfile に opcache.optimization_level=0x7FFFBBFF
を追加しました。
FROM php:7.3-fpm-alpine3.8
RUN apk update \
&& apk upgrade \
&& apk add --no-cache --virtual .gd-deps \
g++ \
make \
autoconf \
&& pecl update-channels \
&& docker-php-ext-install \
opcache \
&& pecl install xdebug-2.7.0beta1 \
&& rm -rf /tmp/pear ~/.pearrc \
&& docker-php-ext-enable xdebug \
&& echo 'opcache.optimization_level=0x7FFFBBFF' >> /usr/local/etc/php/conf.d/opcache.ini
※ 2019-01-28 追記 @tomoyamachi さんのコメント を参考に echo 'zend_extension=xdebug.so' > /usr/local/etc/php/conf.d/xdebug.ini
から docker-php-ext-enable xdebug
に変更。
で、 docker-compose build
, docker-compose up
したところ、見事正常に動作するようになりました!
めでたしめでたし。
※ 2019-01-28 追記
もともと、 echo 'opcache.optimization_level=0x7FFFBBFF' >> /usr/local/lib/php/extensions/no-debug-non-zts-20180731/opcache.so
などという、わけのわからない事を書いていました…正しくは、 /usr/local/etc/php/conf.d/
の下に .ini です。。
echo 'opcache.optimization_level=0x7FFFBBFF' >> /usr/local/etc/php/conf.d/opcache.ini
してる部分、もしかしたら、 /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
に追記の方が作法的には良いかも知れません。
あるいは、自前で用意した .ini であることを明示したファイル名とか。
ところで…
php7.3 docker
でググると @tomoyamachi さんの https://qiita.com/tomoyamachi/items/991a0d149e9585cac15f という記事が見つかりますが、これも php7.3 + xdebug + opcache なはずなのですが…どうやら正常に動いてるっぽい?
おそらく上記記事を書かれたときは php 7.3.0 かと思うのですが、 https://bugs.php.net/bug.php?id=77287 の Bug は php 7.3.0 でも発生するっぽい気が。。。(流し読みしただけなので、間違ってたらスミマセン!)
あるいは https://github.com/tomoyamachi/docker-laravel-fpm-7.3/blob/2f65eb12a6215759c62180585142a4d90bafec91/Dockerfile#L26 にて、 xdebug.so を読み込まないようにコメントアウトしてるから発症しなかった?
ちょっと後で時間がある時に https://github.com/tomoyamachi/docker-laravel-fpm-7.3 をお借りして手元でも試して見ようと思ってます。
※ 2019-01-28 追記 コメントにて、再現性があったとのことなので、上記に打ち消し線を追加しました。また、自分が echo 'zend_extension=xdebug.so' > /usr/local/etc/php/conf.d/xdebug.ini
という手抜きな書き方をしていたせいで、 docker-php-ext-enable xdebug
にて、有効になっていることをすっかり見落としてました…大変失礼しました!