我们的一个开发环境的项目中(php 5.2.17),初始化时,调用session_set_save_handler注册了session的open,close,read,write,destroy,gc方法,并session_start了。

但是连续刷新同一个页面时,仅第一次是正常的,后面就都“服务器无响应”,而apache的error_log中显示“child pid 22924 exit signal Segmentation fault (11)”。

在php手册“http://cn2.php.net/manual/en/function.session-set-save-handler.php”中,有如下的warning:

When using objects as session save handlers, it is important to register the shutdown function with PHP to avoid unexpected side-effects from the way PHP internally destroys objects on shutdown and may prevent the write and close from being called. Typically you should register 'session_write_close' using the register_shutdown_function()  function.

As of PHP 5.0.5 the write and close handlers are called after object destruction and therefore cannot use objects or throw exceptions. Exceptions are not able to be caught since will not be caught nor will any exception trace be displayed and the execution will just cease unexpectedly. The object destructors can however use sessions.

It is possible to call session_write_close() from the destructor to solve this chicken and egg problem but the most reliable way is to register the shutdown function as described above.

The “write” handler is not executed until after the output stream is closed. Thus, output from debugging statements in the “write” handler will never be seen in the browser. If debugging output is necessary, it is suggested that the debug output be written to a file instead.

由上可知,在PHP的某些版本里,session的write和close hanlders是在进程资源回收之后调用的,这时,会导致无法找到相应的handler类,或其使用的对象资源。

将session相关代码提取出来,写了一个测试页面,在php-5.2.17下会报错,但是php-5.3.10下就是正常的。5.2.17下可以通过添加register_shutdown_function(‘session_write_close’),使session的write和close函数提前执行,从而避免错误。

array(
                array( 'host'=>'127.0.0.1', 'port'=>11211),
        ),
        'slave'=>array(
                array( 'host'=>'127.0.0.1', 'port'=>11211),
        ),
));

Crab_Session_Memcached::start();
var_dump($_SESSION);

#register_shutdown_function('session_write_close');


$_SESSION = array('abc' => 123);
var_dump($_SESSION);

echo "I'm here";
exit;

Leave a Reply