时间:2021-05-26
前几天东政同学反馈说Linode服务器快卡死了,今天有时间排查了一下具体原因,最终原因稍微有点悲壮:file_get_contents没有设置超时时间,加上我用的php5.2关于curl的代码有个bug,于是导致PHP进程进入死循环。
今天下午又发现系统负载很高,于是上去看了一下,发现一大坨PHP进程没有退出,占用了很多CPU,如图:
问题进程:
后面运行的脚本是我的RSS定时更新任务,看来PHP代码什么地方有问题,于是strace -p 14043看了一下:
select(5, [4], [4], [], {15, 0}) = 1 (out [4], left {14, 999996})poll([{fd=4, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout)clock_gettime(CLOCK_MONOTONIC, {4582888, 760370017}) = 0clock_gettime(CLOCK_MONOTONIC, {4582888, 760468615}) = 0clock_gettime(CLOCK_MONOTONIC, {4582888, 760565053}) = 0select(5, [4], [4], [], {15, 0}) = 1 (out [4], left {14, 999997})在4号fd上面死循环了,于是看看FD是什么:ll /proc/14043/fd
lrwx—— 1 wuhaiwen wuhaiwen 64 7月 21 11:00 4 -> socket:[53176380]
再看了一下原来是在请求CSDN的一个网页的时候死循环了,但不知道什么地方请求的,想到GDB一下php进程看看,bt显示:
(gdb) bt
#0 0x00007f6721f8f013 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:82
#1 0×0000000000481952 in php_curl_stream_read (stream=0×2280650,
buf=0x22ea5d0 “2Fmit,确实是一个bug, 其实curl_multi_fdset 的文档开头写了的:
复制代码 代码如下:
This function extracts file descriptor information from a given multi_handle. libcurl returns its fd_set sets. The application can use these to select() on, but be sure to FD_ZERO them before calling this function as curl_multi_fdset(3) only adds its own descriptors,
好吧,最后用GDB验证一下,我在上面的do下面,curl_multi_fdset调用之前,手动将fd清空,看看能否退出循环:
(gdb) print FD_ZERO(&curlstream->readfds)
No symbol “FD_ZERO” in current context.
FD_ZERO竟然没有,不管了,其本来是个宏定义,展开就行:#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
直接用call修改curl_muti_fdset的三个参数数组如下:
复制代码 代码如下:
(gdb) call bzero((char *)(&curlstream->readfds), sizeof(*(&curlstream->readfds)))
$5 = 17055392
(gdb) call bzero((char *)(&curlstream->writefds),sizeof(*(&curlstream->writefds)))
$6 = 17055520
(gdb) call bzero((char *)(&curlstream->excfds), sizeof(*(&curlstream->excfds)))
$7 = 17055648
然后GDB单步执行,如期的由于curlstream->pending变为0,从而退出了循环,回到php_stream_fill_read_buffer的大函数了
到此基本结束。有问题的PHP版本应该是5.2. 具体没有细看,读者可以参考下上面的这个提交改动或者直接看自己的版本代码是否有问题。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
PHP匿名函数与注意事项PHP5.2以前:autoload,PDO和MySQLi,类型约束PHP5.2:JSON支持PHP5.3:弃用的功能,匿名函数,新增魔术
步骤一:下载php5.2forwindows的安装包,解压至C:\php。注意此解压目录可以是在任何盘下,然而目录名不能包含空格;以下是php5.2的文件目录:
本文实例讲述了php的ZipArchive类用法,分享给大家供大家参考。具体如下:通常来说,php5.2开始支持ZipArchive类,php4只能使用zip函
用ZipArchive压缩文件,这个是php的扩展类,自php5.2版本以后就已经支持这个扩展,如果你在使用的时候出现错误,查看下php.ini里面的exten
本文实例讲述了PHP5.2中PDO的简单使用方法。分享给大家供大家参考,具体如下:一、PDO配置1、确保PHP版本为5.2.5以上2、在php.ini中找到Dy