Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

开启OPcache,会在请求量大时会报找不到文件 #357

Closed
bigstarsea opened this issue Jun 20, 2017 · 18 comments
Closed

开启OPcache,会在请求量大时会报找不到文件 #357

bigstarsea opened this issue Jun 20, 2017 · 18 comments

Comments

@bigstarsea
Copy link

bigstarsea commented Jun 20, 2017

PHP 7.1.5
OPcache v7.1.5
yaf 3.0.4

请求量大时,会偶尔报找不到 yaf.library 里边的全局类,也偶尔报找不到 项目里配置的 本地类,关闭OPcache之后就没有这些问题了,不晓得是哪里的锅

@laruence
Copy link
Owner

无论是哪里的锅, 我都都背 -_#

但从表象来看应该是opcache的问题, 你能描述的尽量精确些么, 比如做了什么操作后, 发生错误的时候提示信息是什么, 尽量精确

@owenliang
Copy link

我表示一样,稍微上一点并发,就偶现找不到类。 @laruence

PHP7环境,开启了Opcache,apache ab压测,不上并发貌似没事,上了并发就开始蹦错误。

[2048,"Yaf_Loader::autoload(): Could not find class sys_mysql_client in /home/xxxx/yaf/application/library/sys/mysql/client.php","/home/
xxxx/yaf/application/library/sys/mysql/manager.php",31,{"name":"xxxx"}]

@laruence
Copy link
Owner

如果关闭了opcache还有么?

@owenliang
Copy link

@laruence 稍等我试试,另外一个issue也提到了,它还提到3.0.3没有问题,3.0.4出现了,我刚在看diff代码,初步怀疑一下yaf_loader_is_local_namespace函数。

@owenliang
Copy link

owenliang commented Jun 28, 2017

@laruence 关闭opcache就好了~

补充一下现象:1000个并发请求,会有20个左右去全局目录找class,剩余的是在本地类成功找到。

@laruence
Copy link
Owner

为什么你会怀疑 yaf_loader_is_local_namespace 呢? 是说目录位置寻找错了?

@owenliang
Copy link

owenliang commented Jun 28, 2017

@laruence 嗯,是被这个现象带过去的,但是看了函数逻辑,木有找到真相。。

我在Bootstrap里注册了2个local namespace:sys和biz,要加载的类叫做:sys_mysql_manager。

看这个函数意图,是先摘出sys_mysql_manager的sys,然后在Yaf_G(local_namespaces)=sys/biz这个字符串里匹配到sys,最后返回1。

没学过php扩展开发,和Opcache有什么关系。。木有思路了。


应该是我看错了,并没有跑到全局目录去找,只是在本地目录里报找不到。 但是异常里的文件路径都是准确的,结合Opcache,我开始怀疑yaf_loader_import函数了-,-

@owenliang
Copy link

再补充其他错误类型:

[2,"Yaf_Loader::autoload(): Failed opening script /home/liangdong/php7/lib/sys/mysql/manager.php: No such file or directory","/home/liangdong/yaf/application/library/sys/framework/loader.php",19,{"class_name":"sys_mysql_manager"}]Class 'sys_mysql_manager' not found

@laruence
Copy link
Owner

/home/liangdong/php7/lib/sys/mysql/manager.php 那个这个文件真实存在么, 另外php有权限读取这个文件么

@owenliang
Copy link

owenliang commented Jun 28, 2017

我看错了,鸟哥你说的这个文件不存在,那是我的global路径,但是类应该是本地类。 总结起来有2个情况,本地类莫名其妙跑去全局路径加载,本地类在本地路径提示找不到。

@owenliang
Copy link

@laruence ,我提供点辅助信息:

1,yaf-3.0.3开启opcache没有出现该问题。
2,yaf-3.0.4开启opcache有问题,关闭opcache没问题。
3,yaf master HEAD开启opcache有问题,关闭opcache没问题。

同样的问题在issue #320 提到过。


下面是我的PHP环境:

PHP 7.1.5 (cli) (built: May 31 2017 12:58:46) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.1.5, Copyright (c) 1999-2017, by Zend Technologies

[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
hash
iconv
json
libxml
mysqlnd
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
redis
Reflection
session
SimpleXML
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
yaf
Zend OPcache

[Zend Modules]
Zend OPcache

@laruence
Copy link
Owner

你这样, 你可以尝试开启opcache.memory_protect=1 , 看看有没有coredump出来, 如果有把backtrace贴出来

@owenliang
Copy link

owenliang commented Jun 29, 2017

@laruence

Program terminated with signal 11, Segmentation fault.
#0 yaf_loader_is_local_namespace (loader=, class_name=0x7fa2c5a65e70 "sys_framework_loader", len=)
at /home/liangdong/source/yaf-master/yaf_loader.c:155
155 *backup = '\0';
Missing separate debuginfos, use: debuginfo-install cyrus-sasl-lib-2.1.23-15.el6_6.2.x86_64 glibc-2.12-1.192.el6.x86_64 keyutils-libs-1.4-5.el6.x86_64 krb5-libs-1.10.3-42z1.el6_7.x86_64 libcom_err-1.41.12-22.el6.x86_64 libcurl-7.19.7-46.el6.x86_64 libidn-1.18-2.el6.x86_64 libselinux-2.0.94-5.8.el6.x86_64 libssh2-1.4.2-2.el6_7.1.x86_64 libxml2-2.7.6-21.el6_8.1.x86_64 nspr-4.11.0-0.1.el6_7.x86_64 nss-3.21.0-0.3.el6_7.x86_64 nss-softokn-freebl-3.14.3-23.el6_7.x86_64 nss-util-3.21.0-0.3.el6_7.x86_64 openldap-2.4.40-7.el6_7.x86_64 openssl-1.0.1e-48.el6_8.1.x86_64 zlib-1.2.3-29.el6.x86_64
(gdb) bt
#0 yaf_loader_is_local_namespace (loader=, class_name=0x7fa2c5a65e70 "sys_framework_loader", len=)
at /home/liangdong/source/yaf-master/yaf_loader.c:155
#1 0x00007fa2cd086d91 in yaf_internal_autoload (file_name=0x7fa2c5a65e70 "sys_framework_loader", name_len=20, directory=0x7fff99ec44d0)
at /home/liangdong/source/yaf-master/yaf_loader.c:321
#2 0x00007fa2cd086ff1 in zim_yaf_loader_autoload (execute_data=, return_value=0x7fff99ec46c0)
at /home/liangdong/source/yaf-master/yaf_loader.c:689
#3 0x000000000071fce1 in zend_call_function (fci=0x7fff99ec4630, fci_cache=0x7fff99ec4670) at /home/liangdong/php-7.1.5/Zend/zend_execute_API.c:869
#4 0x000000000074e24a in zend_call_method (object=0x7fa2d3673428, obj_ce=, fn_proxy=,
function_name=0x7fa2d365a670 "yaf_loader::autoload\a", function_name_len=24, retval_ptr=0x0, param_count=1, arg1=0x7fa2d36151e0, arg2=0x0)
at /home/liangdong/php-7.1.5/Zend/zend_interfaces.c:99
#5 0x000000000060ec15 in zif_spl_autoload_call (execute_data=, return_value=)
at /home/liangdong/php-7.1.5/ext/spl/php_spl.c:420
#6 0x000000000071fce1 in zend_call_function (fci=0x7fff99ec48a0, fci_cache=0x7fff99ec48e0) at /home/liangdong/php-7.1.5/Zend/zend_execute_API.c:869
#7 0x00000000007205a5 in zend_lookup_class_ex (name=, key=0x7fa2c623b360, use_autoload=)
at /home/liangdong/php-7.1.5/Zend/zend_execute_API.c:1028
#8 0x0000000000720836 in zend_fetch_class_by_name (class_name=0x7fa2c5a65e58, key=, fetch_type=512)
at /home/liangdong/php-7.1.5/Zend/zend_execute_API.c:1463
#9 0x00000000007be99a in ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER (execute_data=0x7fa2d3615110)
at /home/liangdong/php-7.1.5/Zend/zend_vm_execute.h:5479
#10 0x0000000000789d88 in execute_ex (ex=) at /home/liangdong/php-7.1.5/Zend/zend_vm_execute.h:432
#11 0x000000000071fe40 in zend_call_function (fci=0x7fff99ec4b00, fci_cache=0x7fff99ec4b40) at /home/liangdong/php-7.1.5/Zend/zend_execute_API.c:855
#12 0x000000000074e24a in zend_call_method (object=0x7fa2d3665e08, obj_ce=, fn_proxy=,
function_name=0x7fa2cd089c4b "dispatchloopshutdown", function_name_len=20, retval_ptr=0x0, param_count=2, arg1=0x7fa2d3674208, arg2=0x7fff99ec4cd0)
at /home/liangdong/php-7.1.5/Zend/zend_interfaces.c:99
#13 0x00007fa2cd06fb15 in yaf_dispatcher_dispatch (dispatcher=0x7fa2d366a038, response_ptr=)
at /home/liangdong/source/yaf-master/yaf_dispatcher.c:892
#14 0x00007fa2cd06a2a5 in zim_yaf_application_run (execute_data=, return_value=0x7fff99ec4cd0)
at /home/liangdong/source/yaf-master/yaf_application.c:442
#15 0x00000000007ab390 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (execute_data=0x7fa2d3615030) at /home/liangdong/php-7.1.5/Zend/zend_vm_execute.h:970
#16 0x0000000000789d88 in execute_ex (ex=) at /home/liangdong/php-7.1.5/Zend/zend_vm_execute.h:432
#17 0x00000000007d59a0 in zend_execute (op_array=0x7fa2d3674000, return_value=) at /home/liangdong/php-7.1.5/Zend/zend_vm_execute.h:474
#18 0x000000000072e513 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/liangdong/php-7.1.5/Zend/zend.c:1476
#19 0x00000000006ce0a0 in php_execute_script (primary_file=0x7fff99ec73d0) at /home/liangdong/php-7.1.5/main/main.c:2537
#20 0x00000000007e28de in main (argc=, argv=) at /home/liangdong/php-7.1.5/sapi/fpm/fpm/fpm_main.c:1966

@owenliang
Copy link

(gdb) f 0
#0 yaf_loader_is_local_namespace (loader=, class_name=0x7fa2c5a65e70 "sys_framework_loader", len=)
at /home/liangdong/source/yaf-master/yaf_loader.c:155
155 *backup = '\0';
(gdb) info locals
pos = 0x7fa2c5a65e73 "framework_loader"
ns = 0x7fa2d36608d8 "sys:biz"
prefix = 0x7fa2c5a65e70 "sys_framework_loader"
orig_char = 95 '
'
backup = 0x7fa2c5a65e73 "_framework_loader"
prefix_len = 3

@owenliang
Copy link

(gdb) f 1
#1 0x00007fa2cd086d91 in yaf_internal_autoload (file_name=0x7fa2c5a65e70 "sys_framework_loader", name_len=20, directory=0x7fff99ec44d0)
at /home/liangdong/source/yaf-master/yaf_loader.c:321
321 if (yaf_loader_is_local_namespace(loader, file_name, name_len)) {
(gdb) info locals
library_dir =
library_path =
loader = 0x7fa2d367d020
rv = {value = {lval = 0, dval = 0, counted = 0x0, str = 0x0, arr = 0x0, obj = 0x0, res = 0x0, ref = 0x0, ast = 0x0, zv = 0x0, ptr = 0x0, ce = 0x0,
func = 0x0, ww = {w1 = 0, w2 = 0}}, u1 = {v = {type = 0 '\000', type_flags = 0 '\000', const_flags = 0 '\000', reserved = 0 '\000'}, type_info = 0},
u2 = {next = 0, cache_slot = 0, lineno = 0, num_args = 0, fe_pos = 0, fe_iter_idx = 0, access_flags = 0, property_guard = 0, extra = 0}}
status =
q =
p =
directory_len =
buf = {s = 0x0, a = 0}

@owenliang
Copy link

是不是因为class_name是从zend拿的内存:

PHP_METHOD(yaf_loader, autoload) {
char *class_name, *origin_classname, *app_directory, *directory = NULL, *file_name = NULL;
char *dup_lcname = NULL;
size_t separator_len, file_name_len = 0;
size_t class_name_len;
zend_bool ret = 1;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &class_name, &class_name_len) == FAILURE) {
	return;
}

separator_len = YAF_G(name_separator_len);
app_directory = YAF_G(directory)? ZSTR_VAL(YAF_G(directory)) : NULL; 
origin_classname = class_name;

在后面*backup改的是class_name的内存,被Protected搞core了:
int yaf_loader_is_local_namespace(yaf_loader_t *loader, char *class_name, int len) {
char *pos, *ns, *prefix;
char orig_char = 0, *backup = NULL;
size_t prefix_len;

if (!YAF_G(local_namespaces)) {
	return 0;
}

ns = ZSTR_VAL(YAF_G(local_namespaces));

pos = strstr(class_name, "_");
if (pos) {
	prefix_len 	= pos - class_name;
	prefix 	= class_name;
	backup = class_name + prefix_len;
	orig_char = '_';
	*backup = '\0';

owenliang pushed a commit to owenliang/yaf that referenced this issue Jun 29, 2017
@laruence
Copy link
Owner

应该已经修复, 请试用https://pecl.php.net/package/yaf 3.0.5

@owenliang
Copy link

got it~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants