为什么我的PHP与Zend Framework会因为更新到5.4(在文件系统上存在会话之后)"会话已启动"而疯狂?

Auf*_*gel 5 php zend-framework

我的任何项目都没有问题.就在最近,当我在arch linux中运行pacman-update(更新到5.4)时,我的许多项目都不再可以运行了.

有趣的是,只有在文件系统上创建会话文件时才会出现问题.我的意思是,只要/ tmp/sess*不存在,我就可以第一次调用该网站.

当我想第二次调用它并且/ tmp/sess*已经写入时,我收到以下错误(包括stacktrace,Zend Framework).

Zend_Controller_Exception: session has already been started by session.auto-start or session_start()#0 /srv/http/bahasa/library/Zend/Session/Namespace.php(143): Zend_Session::start(true)
#1 /srv/http/bahasa/library/Zend/Auth/Storage/Session.php(87): Zend_Session_Namespace->__construct('Zend_Auth')
#2 /srv/http/bahasa/library/Zend/Auth.php(91): Zend_Auth_Storage_Session->__construct()
#3 /srv/http/bahasa/library/Zend/Auth.php(141): Zend_Auth->getStorage()
#4 /srv/http/bahasa/library/Skoch/Controller/Plugin/Navigation.php(59): Zend_Auth->hasIdentity()
#5 /srv/http/bahasa/library/Zend/Controller/Plugin/Broker.php(287): Skoch_Controller_Plugin_Navigation->dispatchLoopStartup(Object(Zend_Controller_Request_Http))
#6 /srv/http/bahasa/library/Zend/Controller/Front.php(928): Zend_Controller_Plugin_Broker->dispatchLoopStartup(Object(Zend_Controller_Request_Http))
#7 /srv/http/bahasa/library/Zend/Application/Bootstrap/Bootstrap.php(97): Zend_Controller_Front->dispatch()
#8 /srv/http/bahasa/library/Zend/Application.php(366): Zend_Application_Bootstrap_Bootstrap->run()
#9 /srv/http/bahasa/public/index.php(30): Zend_Application->run()
#10 {main} in /srv/http/bahasa/library/Zend/Controller/Plugin/Broker.php on line 312
Run Code Online (Sandbox Code Playgroud)

当然我已经在stackoverflow上检查了这个问题的其他答案,但是:

  • session.auto-start设置为0
  • 在库/ Zend /之外的地方没有session_start()调用(在整个项目目录上都有grep -r)
  • 在Bootstrap.php中编写Zend_Session :: start()(作为错误修复)会导致新的致命错误
  • 文件系统权限没问题,/ tmp有777,创建的sess文件有http rw(777不改变行为).

同样如上所述,一旦我从PHP 5.3更新到PHP 5.4,就会发生奇怪的事情.问题是,降级似乎不起作用(然后mysql库以某种方式被破坏).

正如已经提到的,对我来说最奇怪的是,它只发生在/ tmp中创建会话文件时.当/ tmp没有会话文件时,一切都很完美.

是的,这不仅是我自己的项目受到影响,而且我正在为另一家公司(在他们的服务器和本地PC上运行像魅力)工作,所以这也与我自己的代码中的问题相矛盾(同样的事情发生在两个Zend Framework项目中).

当然,我的项目也在PHP 5.2.12的在线网站空间中运行.

我猜之前的PHP通知也可能很有趣:

Notice: Array to string conversion in /srv/http/bahasa/library/Zend/Session/Exception.php on line 58

Call Stack:
0.0009     134352   1. {main}() /srv/http/bahasa/public/index.php:0
0.2805    3703732   2. Zend_Application->run() /srv/http/bahasa/public/index.php:30
0.2805    3703756   3. Zend_Application_Bootstrap_Bootstrap->run() /srv/http/bahasa/library/Zend/Application.php:366
0.2806    3703876   4. Zend_Controller_Front->dispatch() /srv/http/bahasa/library/Zend/Application/Bootstrap/Bootstrap.php:97
0.2873    3829732   5. Zend_Controller_Plugin_Broker->routeStartup() /srv/http/bahasa/library/Zend/Controller/Front.php:908
0.2873    3829820   6. Skoch_Controller_Plugin_Autologin->routeStartup() /srv/http/bahasa/library/Zend/Controller/Plugin/Broker.php:237
0.2883    3840992   7. Zend_Auth->hasIdentity() /srv/http/bahasa/library/Skoch/Controller/Plugin/Autologin.php:12
0.2884    3841016   8. Zend_Auth->getStorage() /srv/http/bahasa/library/Zend/Auth.php:141
0.2960    3980864   9. Zend_Auth_Storage_Session->__construct() /srv/http/bahasa/library/Zend/Auth.php:91
0.2960    3981072  10. Zend_Session_Namespace->__construct() /srv/http/bahasa/library/Zend/Auth/Storage/Session.php:87
0.2961    3981232  11. Zend_Session::start() /srv/http/bahasa/library/Zend/Session/Namespace.php:143
0.2968    3989956  12. session_start() /srv/http/bahasa/library/Zend/Session.php:469
0.2972    3997536  13. PropelAutoloader->autoload() /srv/http/bahasa/library/Zend/Session.php:0
0.3000    4060508  14. require('/srv/http/bahasa/application/models/bahasa/User.php') /srv/http/bahasa/library/propel-1.6.4/runtime/lib/util/PropelAutoloader.php:108
0.3377    4925056  15. Zend_Session_Exception::handleSessionStartError() /srv/http/bahasa/library/propel-1.6.4/runtime/lib/util/PropelAutoloader.php:16
Run Code Online (Sandbox Code Playgroud)

但是,Propel似乎在自己的代码中没有任何session_start(),所以这不是原因(推动也在于已检查的项目主管).

我个人目前还没有看到这个通知中的全部含义,但是我看的越长,它看起来就越多与错误相关(至少堆栈跟踪,我的意思是通知只是关于数组到字符串的转换).

用于调用Zend_Session :: start()的Backtraces

好的,我在Zend_Session::start()两次被叫时发现了回溯.

第一:

#0  Zend_Session::start(1) called at [/srv/http/bahasa/library/Zend/Session/Namespace.php:143]
#1  Zend_Session_Namespace->__construct(Zend_Auth) called at [/srv/http/bahasa/library/Zend/Auth/Storage/Session.php:87]
#2  Zend_Auth_Storage_Session->__construct() called at [/srv/http/bahasa/library/Zend/Auth.php:91]
#3  Zend_Auth->getStorage() called at [/srv/http/bahasa/library/Zend/Auth.php:141]
#4  Zend_Auth->hasIdentity() called at [/srv/http/bahasa/library/Skoch/Controller/Plugin/Autologin.php:12]
#5  Skoch_Controller_Plugin_Autologin->routeStartup(Zend_Controller_Request_Http Object ([] => Array ([0] => _GET,[1] => _POST),[] => /de/,[] => ,[] => ,[] => ,[] => Array (),[] => ,[] => Array (),[] => ,[] => ,[] => module,[] => ,[] => controller,[] => ,[] => action)) called at [/srv/http/bahasa/library/Zend/Controller/Plugin/Broker.php:237]
#6  Zend_Controller_Plugin_Broker->routeStartup(Zend_Controller_Request_Http Object ([] => Array ([0] => _GET,[1] => _POST),[] => /de/,[] => ,[] => ,[] => ,[] => Array (),[] => ,[] => Array (),[] => ,[] => ,[] => module,[] => ,[] => controller,[] => ,[] => action)) called at [/srv/http/bahasa/library/Zend/Controller/Front.php:908]
#7  Zend_Controller_Front->dispatch() called at [/srv/http/bahasa/library/Zend/Application/Bootstrap/Bootstrap.php:97]
#8  Zend_Application_Bootstrap_Bootstrap->run() called at [/srv/http/bahasa/library/Zend/Application.php:366]
#9  Zend_Application->run() called at [/srv/http/bahasa/public/index.php:29]
Run Code Online (Sandbox Code Playgroud)

第二:

#0  Zend_Session::start(1) called at [/srv/http/bahasa/library/Zend/Session/Namespace.php:143]
#1  Zend_Session_Namespace->__construct(Zend_Auth) called at [/srv/http/bahasa/library/Zend/Auth/Storage/Session.php:87]
#2  Zend_Auth_Storage_Session->__construct() called at [/srv/http/bahasa/library/Zend/Auth.php:91]
#3  Zend_Auth->getStorage() called at [/srv/http/bahasa/library/Zend/Auth.php:141]
#4  Zend_Auth->hasIdentity() called at [/srv/http/bahasa/library/Skoch/Controller/Plugin/Navigation.php:59]
#5  Skoch_Controller_Plugin_Navigation->dispatchLoopStartup(Zend_Controller_Request_Http Object ([] => Array ([0] => _GET,[1] => _POST),[] => /de/,[] => ,[] => ,[] => de,[] => …
Run Code Online (Sandbox Code Playgroud)

Auf*_*gel 10

好的,我发现了错误.这完全不是你能找到的,但一般的答案对其他人来说可能很有意思.

一般答案

该通知确实与错误有关.问题是,Zend_Session_Exception被注册为session_start()的错误处理程序,而session_start()将小通知传递给Zend_Session_Exception.即使它只是一个通知(它不会在生产系统上被解雇,因此它在那里工作),Zend_Session_Exception被触发并设置Zend_Session_Exception::$sessionStartError为错误.

一旦记录了这样的错误,会话就不会注册到Zend_Session.即使session_start()本身返回true

你可以在这一行看到这一点($startedCleanly表示返回值session_start()): if (!$startedCleanly || Zend_Session_Exception::$sessionStartError != null) {

具体答案

在我的特殊情况下,这一切都是由于继承冲突造成的.我没有将Propels(数据库ORM)基类的参数添加到我的子类中.然后PHP发出通知,我应该纠正这个.

因为这样的Propel对象存在于我的session(User)中,所以通知在调用session_start()时被触发.这就是Zend_Session_Exception被警告的原因.然后它如上所述.

还是有问题

我还没有发现,为什么在PHP 5.4中出现了这种行为.我之前没有实现参数,但在解析会话时从未被视为问题.猜猜他们在打开会话值时已经改变了一些东西.