使用场景:用户触发守护进程,并以守护进程的方式在后台执行一些计划任务。
继续跟踪到main.c,找到函数php_handle_aborted_connection,发现ignore_user_abort为false时,则调用zend_bailout退出当前执行的代码,反之则继续执行
所以从ignore_user_abort的函数定义一层层深入进来,不难发现其中的实现其中的实现
参考资料: http://cn.php.net/manual/zh/function.ignore-user-abort.php
定义与用法:
主要使用PHP内置ignore_user_abort函数来完成,函数设置与客户机断开是否会终止脚本的执行,函数返回 user-abort 设置的之前的值(一个布尔值);
语法
ignore_user_abort(setting)
参数 | 描述 |
---|---|
setting | 可选。如果设置为 true,则忽略与用户的断开,如果设置为 false,会导致脚本停止运行。 如果未设置该参数,会返回当前的设置。 |
提示和注释
注释:PHP 不会检测到用户是否已断开连接,直到尝试向客户机发送信息为止。简单地使用 echo 语句无法确保信息发送,参阅 flush() 函数。
示例:
<?php
//忽略用户的停止信号,并一直执行
ignore_user_abort(true);
set_time_limit(0);
while(1)
{
//连接失败
if(connection_status() != CONNECTION_NORMAL)
{
break;//停止守护进程
}
//...do something...
//十秒钟执行一次
sleep(10);
}
?>
查看函数源码,发现只是改变了变量ignore_user_abort的值,代码如下:
PHP_FUNCTION(ignore_user_abort)
{
char *arg = NULL;
int arg_len = 0;
int old_setting;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
return;
}
old_setting = PG(ignore_user_abort);
if (arg) {
//设置ignore_user_abort的值
zend_alter_ini_entry_ex("ignore_user_abort", sizeof("ignore_user_abort"), arg, arg_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
}
RETURN_LONG(old_setting);
}
继续跟踪到main.c,找到函数php_handle_aborted_connection,发现ignore_user_abort为false时,则调用zend_bailout退出当前执行的代码,反之则继续执行
PHPAPI void php_handle_aborted_connection(void)
{
TSRMLS_FETCH();
PG(connection_status) = PHP_CONNECTION_ABORTED;
php_output_set_status(0 TSRMLS_CC);
//没有设置ignore_user_abort变量为true,则中止执行
if (!PG(ignore_user_abort)) {
zend_bailout();
}
}
同样,在mod_php5API函数接口中可以找到sapi_apache_ub_write,其中ub是unbuffer的意思,此函数是apache在向客户端写数据超时的调用的
static int sapi_apache_ub_write(const char *str, uint str_length TSRMLS_DC)
{
int ret=0;
if (SG(server_context)) {
ret = rwrite(str, str_length, (request_rec *) SG(server_context));
}
if (ret != str_length) {
php_handle_aborted_connection();
}
return ret;
}
所以从ignore_user_abort的函数定义一层层深入进来,不难发现其中的实现其中的实现
参考资料: http://cn.php.net/manual/zh/function.ignore-user-abort.php