幾臺使用了 nginx+php-fpm 的機器上,偶爾能看到php-fpm.log中有這樣的內容
Oct 28 23:13:53.849419 [NOTICE] fpm_got_signal(), line 73: received SIGCHLD
Oct 28 23:13:53.849490 [WARNING] fpm_children_bury(), line 229: child 15044 (pool default) exited on signal 11 SIGSEGV after 1.332818 seconds
Oct 28 23:13:53.850341 [NOTICE] fpm_children_make(), line 305: child 15122 (pool default) started
如果得到SIGSEGV信號的進程比較多的話,還能看到如下的日志
Oct 28 09:03:15.812009 [WARNING] fpm_children_bury(), line 256: failed processes threshold (10 in 60 sec) is reached, initiating reload
Oct 28 09:03:15.812030 [NOTICE] fpm_pctl(), line 208: switching to 'reloading' state
然后php-fpm就會重啟。其中的
failed processes threshold (10 in 60 sec) is reached
是在php-fpm.conf中設置的,表示在60秒內出現SIGSEGV或者SIGBUS錯誤的php-cgi進程數如果超過10個,php-fpm就會重啟。可以通過把php-fpm.conf中的 emergency_restart_threshold的值設置的大一些來增加這個重啟的閥值,比如增加到60個,在有些時候,這能夠避免php-fpm重啟,但這并不是解決問題的根本辦法
SIGSEGV信號一般表示
SIGSEGV --- Segment Fault. The possible cases of your encountering this error are:
1.buffer overflow --- usually caused by a pointer reference out of range.
2.stack overflow --- please keep in mind that the default stack size is 8192K.
3.illegal file access --- file operations are forbidden on our judge system
其中的第三條,跟本問題的關系比較大。也就是php-cgi訪問了一個不存在的或者沒有權限訪問的文件
我用的php-fpm補丁是0.5.8版的,按照一些說法,只要設置了
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
之后,php-cgi如果找不到文件或者沒有權限訪問的話 會提示No input file specified. 或者Access denied.
問題到這里似乎又陷入了僵局
后來又在php.ini中找到了php-cgi的一個參數 cgi.fix_pathinfo
cgi.fix_pathinfo boolean
對 CGI 提供了真正的 PATH_INFO/PATH_TRANSLATED 支持。以前 PHP 的行為是將 PATH_TRANSLATED 設為 SCRIPT_FILENAME,而不管 PATH_INFO 是什么。有關 PATH_INFO 的更多信息見 cgi 規格。將此值設為 1 將使 PHP CGI 修正其路徑以遵守規格。設為 0 將使 PHP 的行為和從前一樣。默認為零。用戶應該修正其腳本使用 SCRIPT_FILENAME 而不是 PATH_TRANSLATED。
把這個參數的值設置為1 ,cgi會多做一些檢查,來判斷請求的路徑中,那部分是文件名,哪部分是路徑名
下面是google groups上的一段話
when cgi.fix_pathinfo was set to "1" it caused a lot of checks in order to find which part of SCRIPT_FILENAME is a file name and which is PATH_INFO. In case of missing file it caused NULL
in path_translated, which caused the crash.
此問題已經耗費了我太多的精力,已經不愿意多花時間去查問題了。比如,可以使用gbd來查看php-cgi 出錯以后產生的dump文件。但這個問題只是偶爾發生,很難捕捉到。如果有兄弟也遇到這個問題,或者你有更好的解決辦法,不妨大家交流一下
修改此參數后,觀察了一段時間,SIGSEGV錯誤在一些服務器上確實消失了。
補充一下 11月10日早上6點半左右到9點26分,三臺服務器(給校內網做的app)同時出現了大量的SIGSEGV錯誤,校內的服務器出的故障,在我這幾臺服務器上產生了大量的不正確的 post / ,后來問校內的工程師,他們只說服務down掉了,卻不肯略微詳細的說一下情況。后來我模擬這些post,確沒出問題??奇怪了