#6 0x00000000006c2a59 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fff376edc60) at /home/wuhaiwen/install/php-env/src/php/php-5.2.8/Zend/zend_vm_execute.h:200
#7 0x00000000006c239f in execute (op_array=0x1f26730) at /home/wuhaiwen/install/php-env/src/php/php-5.2.8/Zend/zend_vm_execute.h:92
·············
#16 0x0000000000730d8e in main (argc=4, argv=0x7fff376f2468) at /home/wuhaiwen/install/php-env/src/php/php-5.2.8/sapi/cli/php_cli.c:1133
看一下当前PHP执行的脚步是什么:
(gdb) p *op_array
$4 = {type = 2 ' 02', function_name = 0x1e54278 "getContent", scope = 0x1f8e850, fn_flags = 257, prototype = 0x0, num_args = 2, required_num_args = 1, arg_info = 0x1fd5e20,
pass_rest_by_reference = 0 ' 00', return_reference = 0 ' 00', refcount = 0x1fd3ab8, opcodes = 0x1fddcc8, last = 28, size = 28, vars = 0x1fd3cc0, last_var = 6, size_var = 16, T = 15,
brk_cont_array = 0x0, last_brk_cont = 0, current_brk_cont = 4294967295, try_catch_array = 0x0, last_try_catch = 0, static_variables = 0x0, start_op = 0x0, backpatch_count = 0,
done_pass_two = 1 ' 01', uses_this = 0 ' 00', filename = 0x1fd3b58 "/home/wuhaiwen/webroot/kulvrss/libs/Myrss/Model/UrlContenter.php", line_start = 9, line_end = 30, doc_comment = 0x0,
doc_comment_len = 0, reserved = {0x0, 0x0, 0x0, 0x0}}
找到了问题代码位置,原来是一个file_get_contents($url)调用,没有设置超时时间,于是PHP卡死在网络请求了。于是用stream_context_create 设置超时时间搞定。
到这里 似乎问题解决了,但是,为什么没有设置超时时间就导致php进程占用CPU,系统负载那么高?按理说应该等待I/O才是呀?看上面CPU情况,完全是进入了死循环的节奏。
根据上面的bt堆栈,首先看倒数第二个函数的调用:
#1 0×0000000000481952 in php_curl_stream_read (stream=0×2280650,
buf=0x22ea5d0 “2Fwww.laruence.com%2Ftag%2F%25e6%25ad%25a3%25e5%2588%2599%27+class%3D%27tag-link-191%27+title%3D%273+topics%27+style%3D%27font-size%3A+9.0243902439pt%3B%27%3E%E6%AD%A3%E5%88%99%3C%2Fa%3E%3C%2Ftags%3E”"…, count=8192) at /home/wuhaiwen/install/php-env/src/php/php-5.2.8/ext/curl/streams.c:169
看一下代码,我用的事5.2.8版本的PHP,比较老。代码如下:
static size_t php_curl_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
{
php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
size_t didread = 0;
if (curlstream->readbuffer.readpos >= curlstream->readbuffer.writepos && curlstream->pending) {
//········
do {
/* get the descriptors from curl */
curl_multi_fdset(curlstream->multi, &curlstream->readfds, &curlstream->writefds, &curlstream->excfds, &curlstream->maxfd);
/* if we are in blocking mode, set a timeout */
tv.tv_usec = 0;
tv.tv_sec = 15; /* TODO: allow this to be configured from the script */
/* wait for data */
switch (select(curlstream->maxfd + 1, &curlstream->readfds, &curlstream->writefds, &curlstream->excfds, &tv)) {
case -1:
/* error */
return 0;
case 0:
/* no data yet: timed-out */
return 0;
default:
/* fetch the data */
do {
curlstream->mcode = curl_multi_perform(curlstream->multi, &curlstream->pending);
} while (curlstream->mcode == CURLM_CALL_MULTI_PERFORM);
}
} while (curlstream->readbuffer.readpos >= curlstream->readbuffer.writepos && curlstream->pending > 0);
}
//··········
return didread;
}







