我们的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设置为最大值,这也适用。