我使用的是python 2.7
我想在fcntl.flock()周围创建一个包装器函数,它将在设置的时间间隔后超时:
wrapper_function(timeout):我尝试在另一个线程上调用并使用thread.join(超时),但fcntl.flock()似乎继续阻塞:
def GetLock(self, timeout):
"""Returns true if lock is aquired, false if lock is already in use"""
self.__lock_file = open('proc_lock', 'w')
def GetLockOrTimeOut():
print 'ProcessLock: Acquiring Lock'
fcntl.flock(self.__lock_file.fileno(), fcntl.LOCK_EX)
print 'ProcessLock: Lock Acquired'
thread = threading.Thread(target=GetLockOrTimeOut)
thread.start()
thread.join(timeout)
if thread.isAlive():
print 'GetLock timed out'
return False
else:
return True我已经研究了终止线程的解决方案,最流行的解决方案似乎是对threading.thread进行子类化,并添加一个在线程中引发异常的功能。但是,我遇到了一个link,它说这个方法不能与本机调用一起工作,我非常确定fcntl.flock()正在调用本机函数。有什么建议吗?
上下文:我使用文件锁来创建一个单实例应用程序,但我不希望该应用程序的第二个实例在第一个实例终止之前一直处于挂起状态。
发布于 2011-03-10 12:30:31
系统调用的超时是通过信号完成的。当信号发生时,大多数阻塞系统调用都会返回EINTR,因此可以使用alarm实现超时。
这里有一个上下文管理器,它可以处理大多数系统调用,如果它花费的时间太长,会导致IOError从阻塞的系统调用中引发。
import signal, errno
from contextlib import contextmanager
import fcntl
@contextmanager
def timeout(seconds):
def timeout_handler(signum, frame):
pass
original_handler = signal.signal(signal.SIGALRM, timeout_handler)
try:
signal.alarm(seconds)
yield
finally:
signal.alarm(0)
signal.signal(signal.SIGALRM, original_handler)
with timeout(1):
f = open("test.lck", "w")
try:
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
except IOError, e:
if e.errno != errno.EINTR:
raise e
print "Lock timed out"发布于 2011-03-10 11:50:15
我确信有几种方法,但是使用非阻塞锁怎么样?尝试n次后,放弃并退出吗?
要使用非阻塞锁,请包括fcntl.LOCK_NB标志,如下所示:
fcntl.flock(self.__lock_file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)发布于 2015-09-15 15:32:58
我喜欢在这里蜂拥而至,因为尝试使用超时进行阻塞锁需要更改全局状态,这使得对您的程序进行推理变得更加困难,特别是在涉及线程的情况下。
您可以像上面那样派生子进程并实现警报,也可以只执行http://man7.org/linux/man-pages/man1/flock.1.html
import subprocess
def flock_with_timeout(fd, timeout, shared=True):
rc = subprocess.call(['flock', '--shared' if shared else '--exclusive', '--timeout', str(timeout), str(fd)])
if rc != 0:
raise Exception('Failed to take lock')如果您有一个足够新的flock版本,您可以使用-E为命令指定一个不同的退出代码,否则命令会成功,但在超时后无法获得锁,因此您可以知道命令是否由于其他原因而失败。
https://stackoverflow.com/questions/5255220
复制相似问题