[英]php is locking a deleted session file
我们的php应用程序在apache下运行,偶尔会尝试锁定已删除的会话文件,这会挂起apache进程并最终耗尽进程。
证据 :
strace : flock(89, LOCK_EX -----stuck in flock for File Descriptor 89
然后 :
lsof,对于同样的过程:
httpd 22161 apache 89u ... /var/lib/php/session/sess_mf7svvirg7rbu9l0m5999pm6h4 (deleted)
有关为什么会发生这种情况的任何想法? 我们可以做些什么来阻止它呢?
我遇到了与你的症状相同的问题,除了会话文件是否被删除是无关紧要的(也可能适合你 - 你有证据表明删除会话文件与flock
吗?)。
就我而言,在两个脚本之间访问同一会话文件是一种竞争条件:
/page1.php
在加载时执行正常。 它包括对/background.php
执行XMLHttpRequest的javascript。 /background.php
,它运行readfile(http://remote.url)
,这是一个不存在的URL。 /page2.php
,脚本停止运行。 strace显示flock(89, LOCK_EX
和lsof表示它正在等待会话文件的读/写访问。 在这种情况下,/ /page2.php
和/background.php
都在同一会话文件上等待,但后者无法这样做,因为它等待readfile()
超时。 我在php_error_log
得到了这个:
PHP Warning: readfile(http://remote.url): failed to open stream: Connection timed out in […]/background.php on line […]
所以问题在于与完全不同的脚本而不是感知到的罪魁祸首。
您可以通过浏览php会话文件的所有打开文件来快速检查此问题,以查看哪个httpd进程正在使用它:
$ sudo lsof | grep sess_it9q6kkvf83gcj72vu05p9fcad7
httpd 31325 apache 74u REG 8,5 410 11634061 /var/lib/php/session/sess_it9q6kkvf83gcj72vu05pfa543
httpd 31632 apache 74uW REG 8,5 410 11634061 /var/lib/php/session/sess_it9q6kkvf83gcj72vu05pfa543
如果两个httpd进程正在访问同一个会话文件,那么这可能是您的问题。 现在您可以使用strace检查这些进程正在执行的操作,或者在我的情况下,使用apachectl fullstatus
就足够了:
$ sudo apachectl fullstatus | grep 31632
5-7 31632 0/1/1169 _ 0.05 6 30692 0.0 0.02 3.45 111.222.333.444 www.example.com.com /background.php
是否有任何巨大的(客户端)需要删除会话文件? 你不应该这样做。 PHP本身实现了一个垃圾收集机制来删除已解散的会话文件。 它将比使用PHP自己编写的任何其他内容更有效 。
您可以使用:
并再次执行session_start()。
在这里查看更多。
更新:
PHP是一个非常干净的脚本引擎,它不会在您的系统上留下垃圾! 达到会话超时后会自动删除会话文件。 session-timeout
可能是您的系统的情况我认为如此。 因此,如果超时设置为20分钟,则文件将在上次访问后20分钟删除。 对于cookie也是如此。 每次请求页面时,cookie-ttl设置为现在+ 20分钟。
查看一些配置指令 。 可能性是您已将gc_maxlifetime设置为非常高的值,并且它们根本没有达到“到期”限制以自动收集。 您应该检查您的应用程序,以确保它们没有在运行时为会话设置设置奇怪的值(使用ini_set()
)。
PHP有一个内部算法,在session_start()
上运行,决定它是否应该执行垃圾清理运行并删除旧的会话文件。 出于性能原因,我认为每次运行的默认机会是1%,因此平均每100个session_start()调用将启动一次垃圾收集例程。 如果您发现这还不够,可以将gc_divisor设置提高到高于1的值。
不知道为什么你的情况。
这个问题得到了一些好的建议......
您是否尝试重新安装环境或迁移到其他服务器? 如果你否决了默认会话处理程序并使用fopen($ file,'w')而不是fopen($ file,'x'),它会工作吗?
此外,基于数据库实现会话处理程序的解决方法,例如,有一百万左右的指南来设置“php和mysql会话处理程序”。
对于您的情况,这可能更像是一种解决方法,但为什么不将会话从文件系统迁移到数据库呢?
你可以在这里获得更多信息http://php.net/manual/en/function.session-set-save-handler.php
你有没有尝试过阅读这两个漏洞?
https://bugs.php.net/bug.php?id=47640 https://bugs.php.net/bug.php?id=32092
尝试调用session_write_close()(丑陋的解决方法)作为最后一行或升级PHP。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.