我们的 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() 正在做什么,因为我没有找到对应的系统调用。
附注我们删除了所有包含 sem_*() 的语句,似乎我们不再遇到这个问题。
最佳答案
您需要立即停止使用 @ 运算符。这会掩盖任何错误,并使其默默地被忽略,即使它会导致致命退出。
@ 运算符是 PHP 最糟糕的功能之一。
如果发生错误,因为您使用的是 @ 运算符,您无法知道它是什么,甚至根本不知道它发生过,因为您的脚本要么继续运行,要么在没有诊断数据的情况下退出。即使您设置了错误日志记录并将 error_reporting 设置为最大值,这也适用。
关于PHP 信号量导致失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7199814/