ZF-12494: Zend_Session error handlers should test current error reporting level (for @-silenced-functions)

Description

Somewhere in my code I'm storing a {{Zend_Ldap_Node}} into Session. I've just upgraded this application from ZF 1.10 to ZF 1.12 and since then I'm getting bq. Uncaught exception 'Zend_Session_Exception' with message 'session has already been started by session.auto-start or session_start()'"

h3. Errors

Call stack is complaining about an already started Session: ||#||Time||Memory||Function||Location|| |1|0.0061|343536|{main}( )|..\index.php:0| |2|0.2549|11626392|Zend_Application->run( )|..\index.php:38| |3|0.2549|11626392|Zend_Application_Bootstrap_Bootstrap->run( )|..\Application.php:366| |4|0.2552|11626448|Zend_Controller_Front->dispatch( ???, ??? )|..\Bootstrap.php:97| |5|0.4126|15116600|Zend_Controller_Plugin_Broker->preDispatch( ??? )|..\Front.php:941| |6|0.4162|15164720|Zend_Controller_Plugin_ErrorHandler->preDispatch( ??? )|..\Broker.php:309| |7|0.4163|15164720|Zend_Controller_Plugin_ErrorHandler->_handleError( ??? )|..\ErrorHandler.php:212|

But variables in local scope (#7) (xDebug infos) shows a {{Zend_Session_Exception}} with a message related to {{unserialize()}} and {{Zend_Ldap_Converter::fromLdapUnserialize()}}: {quote} Zend_Session::start() - D:_ Libraries\Zend Framework 1.12.1\library\Zend\Ldap\Converter.php(Line:395): Error #8 unserialize() function.unserialize]: Error at offset 0 of 174474 bytes D:_ Libraries\Zend Framework 1.12.1\library\Zend\Ldap\Converter.php(Line:395): Error #8 unserialize() [function.unserialize]: Error at offset 0 of 174474 bytes D:_ Libraries\Zend Framework 1.12.1\library\Z'... {quote}

h3. Code analysis

After some deep tests I've determined that the error handlers that {{Zend_Session::start()}} uses (namely {{Zend_Session_Exception::handleSessionStartError()}} are fired when {{Zend_Ldap_Converter::fromLdapUnserialize()}} tries to unserialize a value despite the whole unserialize-failure management in place (id. ignoring {{unserialize()}} error messages with the @ error control operator). Then a {{Zend_Session_Exception}} is thrown by {{Zend_Session::start()}} with the {{Zend_Session_Exception::$sessionStartError}} message that {{unserialize()}} sent.

h3. Reproduction code

With LDAP involved, I thought it would be hard to reproduce, but the problem would occurs anytime a @-silenced function/method called during {{Zend_Session}} is in error. I've set up a whole new ZF project with ZF CLI Tool and tried to reproduce the scenario as simply as possible using a model implementing {{__wakeup()}} and a {{Zend_Controller_Action}} to test it. See code on Gist: https://gist.github.com/4440257

h3. Fix proposal

According to [Error Control Operators PHP documentation, custom error handlers are expected to be called in such cases, but {{error_reporting()}} can be used to test if the error was supposed to be ignored (was preceded by @).

See patch proposal on Gist: https://gist.github.com/4440268

Comments

Added gist link to reproduction code and fix proposal.

As advised on IRC channel #zftalk.dev, a possible workaround is to silence the Zend_Session Exception itself by calling {{Zend_Session::setOptions(array('throw_startup_exceptions' => 0))}} prior to any {{Zend_Session::start()}}.

This issue has been closed on Jira and moved to GitHub for issue tracking. To continue following the resolution of this issues, please visit: https://github.com/zendframework/zf1/issues/44