关于php的set_time_limit和进程结束的问题

来源:互联网 发布:电子商务软件下载 编辑:程序博客网 时间:2024/04/26 05:57

今日写了个php程序,其大概下:

<?phpset_time_limit(0);require '../lib/Redis.class.php';require '../config.php';//define('PUSH_URL',"ssl://gateway.sandbox.push.apple.com:2195");define('PUSH_URL','ssl://gateway.push.apple.com:2195');$redis = new Redis();$key = "push_queue";while (1){    $len = $redis->llen($key);    //push的时间为早晨9点到晚上10点    $hour = intval(date("H"));    if($hour>=9 && $hour<=22 && $len>0){$data = $redis->rpop($key);if (empty($data)){sleep(5);}if (!empty($data['device_token']) && !empty($data['content'])){push($data['device_token'], $data['content'],$data['ck']);//echo ($data['device_token']);}    }else{        sleep(5);    }}function push($device_token,$content,$ck){    $deviceToken = trim($device_token);    $body = array("aps" => array("alert" => "$content", "badge" => 1, "sound" => 'received5.caf'));    $ctx = stream_context_create();    stream_context_set_option($ctx, "ssl", "local_cert",$ck);    $fp = stream_socket_client(PUSH_URL, $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);    if (!$fp) {            //print "Failed to connect $err $errstr";            return array('e'=>$err, 'ee'=>$errstr);    }    //print "Connection OK\n";    $payload = json_encode($body);    $msg = chr(0) . pack("n",32) . pack("H*", $deviceToken) . pack("n",strlen($payload)) . $payload;    //print "sending message :" . $payload . "\n";    fwrite($fp, $msg);    fclose($fp);}

其实一看就知道这个是个死循环,用来做daemon进程的。但是先在浏览器测测,然后问题就来了。

我以为set_time_limit只是控制php的脚本执行时间,不会影响浏览器中停止脚本执行。但是我太天真了,我发现我就算在浏览器中终止了php脚本执行,发现nginx下的php-cgi仍然没有结束,就算把浏览器关了,改php-cgi进程还在执行中。


浏览器中脚本执行超时,但php-cgi仍然没终止


从上面的process看出,已经有了两个php-cgi进程都在跑我上面的程序。一个休眠了,另一个正在运行。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

再次关注set_time_limit函数

在stackoverflow看到过这么一个问题

http://stackoverflow.com/questions/7493023/why-doesnt-set-time-limit-work-as-expected

<?
set_time_limit(5);
sleep(30);
echo 'done';
?>

这个程序会运行30s而不是5s。运行环境是Nginx + PHP_FPM。

而接下来的程序这是只运行5s

<?
set_time_limit(5);
while(true==true){
}
sleep(30);
echo 'done';
?>

再翻看php手册,下面有这么一段话

Note: The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real. 

原来set_time_limit()只控制到脚本自身的执行时间按,而系统调用如system() 、流操作、数据库查询操作等都不计算在内。第一个成都的sleep是系统调用,所以不计算在内。