有一种便携式的方式可以在flock()上设置超时时间吗?

17

flock()是PHP的可移植咨询文件锁定函数。他们明确宣传它甚至在Windows下也可以使用:

flock()允许您执行一个简单的读写模型,可用于几乎所有平台(包括大多数Unix衍生产品甚至Windows)。

我想在阻塞的flock()上设置一个可移植的超时(而不是使用LOCK_NB选项的忙等待工作区)。在UNIX中,这可以通过设置会发送SIGALRM的警报来轻松实现:

pcntl_signal(SIGALRM, function() {});
pcntl_alarm(3);
try {
    if (!flock($handle, LOCK_EX)) {
        throw new \Exception("Timeout");
    }
} finally {
    pcntl_alarm(0);
    pcntl_signal_dispatch();
    pcntl_signal(SIGALRM, SIG_DFL);
}

有一种便携式的方法可以对阻塞的flock()设置超时吗?如果有,怎么做?


2
LOCK_NB + 一个循环 + usleep - zerkms
2
没有忙等待的解决方法,使用LOCK_NB选项。 - Markus Malkusch
@zerkms 我相信他已经在那里找过了... 实际上,PHP中没有一种可移植的方法来实现这一点。Windows有一个警报功能,但它并没有通过PHP的任何扩展公开。 - bwoebi
@bwoebi 嗯,他们决定玩挑剔。我也是——在那个页面上(或者在PHP源代码中)解释了flock能做的一切。PS:即使使用繁忙等待循环优雅地处理它,甚至终止进程都是奇怪的。 - zerkms
评论变得太啰嗦了,偏离了实际问题。但我想补充一点,在UNIX中您不必终止进程。flock()将通过返回值指示其失败。为了防止终止,可以为SIGALRM安装一个noop信号处理程序。这不需要任何exec()或其他进程。如果没有可移植的选项,那么我将简单地接受第一个“不,没有可移植的超时”答案。 - Markus Malkusch
显示剩余4条评论
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
3

我认为在Windows上没有任何方法可以避免忙等待/轮询循环来实现此功能。

PHP使用LockFileEx在Windows上实现flock(参见flock_compat.c:132)。从这些类似的问题中可以看出,无法在LockFileEx上设置超时或取消等待LockFileEx请求的进程(即没有相当于SIGALRM信号的用例):

  1. 带有超时的LockFile?(2011年提问)

问:如果我想要等待文件锁,同时又希望有超时处理,应该如何实现?

...

答:编写一个小循环以检查返回代码。

  1. "LockFileEx无法超时,它只会挂起" 来自于1997年的 microsoft.public.win32.programmer.kernel 邮件列表。

问:有人知道如何让 LockFileEx 超时吗?

...

答:你只能让它立即失败,sleep,并循环回来,直到达到某个重试次数限制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,