|
@@ -31,6 +31,7 @@ import subprocess
|
|
|
import glob
|
|
|
import traceback
|
|
|
import errno
|
|
|
+import signal
|
|
|
from commands import getstatusoutput
|
|
|
from contextlib import contextmanager
|
|
|
|
|
@@ -412,10 +413,30 @@ def fileslocked(files):
|
|
|
for lock in locks:
|
|
|
bb.utils.unlockfile(lock)
|
|
|
|
|
|
-def lockfile(name, shared=False, retry=True):
|
|
|
+@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)
|
|
|
+
|
|
|
+def lockfile(name, shared=False, retry=True, block=False):
|
|
|
"""
|
|
|
- Use the file fn as a lock file, return when the lock has been acquired.
|
|
|
- Returns a variable to pass to unlockfile().
|
|
|
+ Use the specified file as a lock file, return when the lock has
|
|
|
+ been acquired. Returns a variable to pass to unlockfile().
|
|
|
+ Parameters:
|
|
|
+ retry: True to re-try locking if it fails, False otherwise
|
|
|
+ block: True to block until the lock succeeds, False otherwise
|
|
|
+ The retry and block parameters are kind of equivalent unless you
|
|
|
+ consider the possibility of sending a signal to the process to break
|
|
|
+ out - at which point you want block=True rather than retry=True.
|
|
|
"""
|
|
|
dirname = os.path.dirname(name)
|
|
|
mkdirhier(dirname)
|
|
@@ -428,7 +449,7 @@ def lockfile(name, shared=False, retry=True):
|
|
|
op = fcntl.LOCK_EX
|
|
|
if shared:
|
|
|
op = fcntl.LOCK_SH
|
|
|
- if not retry:
|
|
|
+ if not retry and not block:
|
|
|
op = op | fcntl.LOCK_NB
|
|
|
|
|
|
while True:
|