5

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

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

当我想第二次调用它并且 /tmp/sess* 已经写入时,我收到以下错误(包括堆栈跟踪、Zend 框架)。

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

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

  • session.auto-start 设置为 0
  • 在 library/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

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

我个人还没有看到这个通知的全部含义,但是我看的时间越长,它似乎与错误相关的越多(至少是堆栈跟踪,我的意思是通知只是关于数组到字符串的转换)。

调用 Zend_Session::start() 的回溯

好的,我在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]

第二:

#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,[] => …
4

4 回答 4

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 对象存在于我的会话 ( User) 中,所以在调用 session_start() 时会触发通知。这就是 Zend_Session_Exception 被警告的原因。然后它就像上面描述的那样。

仍然悬而未决的问题

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

于 2012-06-29T17:21:34.173 回答
4

如果您在从 PHP 5.3 升级到 PHP 5.4+ 后遇到 Zend_Session_Exception,则问题可能是由E_STRICT错误引起的。在 PHP 5.4E_STRICT中成为E_ALL.

您可以在 php.ini 中禁用严格错误:

error_reporting = E_ALL & ~E_STRICT

您会期望异常会消失,但问题在于 Zend_Session 类中的以下几行:

$errorLevel = (is_int(self::$_throwStartupExceptions)) ? self::$_throwStartupExceptions : E_ALL;

// some code omitted
set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), $errorLevel);

// some code omitted
set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), $errorLevel);

error_reporting基本上, Zend_Session_Exception 被注册为一个错误处理程序,如果您不设置该throw_startup_exceptions选项,它将为所有错误级别(不管设置的设置)调用。

我的解决方案是将选项设置throw_startup_exceptions为,false直到我修复代码中的严格/通知错误。

您可以在 application.ini 中设置它:

resources.session.throw_startup_exceptions = false

或致电Zend_Session::setOptions()

于 2014-09-17T15:13:39.337 回答
1

清除浏览器的 cookie。PHP 会话似乎将 SID 存储在 cookie 中,因此当我从 php 5.3 切换到 5.4 时,似乎在处理会话的现有 cookie 值时出现了一些问题。简单地清除会话数据是不够的 - 尝试清除所有会话数据并删除浏览器 cookie。

于 2013-05-29T20:46:38.800 回答
0

在我的情况下,它只是允许会话目录的写入模式

于 2013-05-31T13:22:49.237 回答