PHP 信号量导致失败?
我们的 Web 服务器发现某些涉及信号量的请求随机出现 PHP 请求失败。我们追踪并怀疑该请求由于 PHP 中的 sem_*() 函数而在某处终止,但我们无法从错误日志中挖掘任何有用的信息。我们在 64 位 Linux 机器上使用 PHP 5.3.6。代码运行如下:
$sem_id = @sem_get(123457, 1);
if (!$sem_id) return;
$sem_retval = @sem_acquire($sem_id);
if (!$sem_retval) return;
$shm_id = shmop_open(ftok('/some/path', 'h'), 'c', 0666, 8192);
if ($shm_id === FALSE) { @sem_release($sem_id); return; }
$str = shmop_read($shm_id, 0, 8192);
// ... some operations that may result in changes to $data
if ($data_updated) {
shmop_write($shm_id, str_pad(serialize($data), 8192, "\0"), 0);
}
@shmop_close($shm_id);
@sem_release($sem_id);
@sem_remove($sem_id);
该代码片段位于并发访问非常频繁的区域。事实上,它被放置在我们内部开发的 StreamWrapper 实现中,用于支持我们自己的操作。并发性似乎是相关的,因为我们按顺序进行了测试,没有发现任何问题。
关于可能的原因有什么见解吗?另外,我不确定 sem_remove() 正在做什么,因为我没有找到对应的系统调用。
PS 我们删除了所有包含 sem_*() 的语句,似乎我们不再遇到这个问题。
Our web servers have seen random PHP request failures for some requests that involve semaphores. We traced and suspected the request died somewhere due to sem_*() functions in PHP but we were unable to dig anything useful from the error log. We are on PHP 5.3.6 on 64-bit Linux machines. The code runs like this:
$sem_id = @sem_get(123457, 1);
if (!$sem_id) return;
$sem_retval = @sem_acquire($sem_id);
if (!$sem_retval) return;
$shm_id = shmop_open(ftok('/some/path', 'h'), 'c', 0666, 8192);
if ($shm_id === FALSE) { @sem_release($sem_id); return; }
$str = shmop_read($shm_id, 0, 8192);
// ... some operations that may result in changes to $data
if ($data_updated) {
shmop_write($shm_id, str_pad(serialize($data), 8192, "\0"), 0);
}
@shmop_close($shm_id);
@sem_release($sem_id);
@sem_remove($sem_id);
This snippet is in an area having very frequent access with concurrency. In fact this is placed in a StreamWrapper implementation we developed internally for supporting our own operations. It appears like concurrency is related because we tested sequentially and did not reveal any issues.
Any insights as to what may be the cause? Also, I am not sure what sem_remove() is doing as I found no system call counterpart.
P.S. We took away all statements that contain sem_*() and seems like we no longer experience the issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要立即停止使用 @ 运算符。这会掩盖任何错误,并使其默默地被忽略,即使它会导致致命退出。
@ 运算符是 PHP 最糟糕的功能之一。
如果发生错误,因为您使用的是 @ 运算符,您无法知道它是什么,甚至根本不知道它发生过,因为您的脚本要么继续运行,要么在没有诊断数据的情况下退出。即使您设置了错误日志记录并将 error_reporting 设置为最大值,这也适用。
You need to STOP using the @-operator, right away. This masks any error, and makes it silently ignored, even if it causes a fatal exit.
The @ operator is one of the worst features of PHP.
If an error happens, because you're using the @ operator, you've got no way of knowing what it was, or even that it happened at all, because your script will either plough on regardless, or exit with no dignostic data. This applies even if you've got error logging set up and error_reporting set to its maximum.