aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbitbake/bin/bitbake1
-rw-r--r--bitbake/lib/bb/cooker.py29
-rw-r--r--bitbake/lib/bb/tinfoil.py5
-rw-r--r--bitbake/lib/bb/ui/knotty.py43
-rw-r--r--bitbake/lib/bb/utils.py29
5 files changed, 84 insertions, 23 deletions
diff --git a/bitbake/bin/bitbake b/bitbake/bin/bitbake
index a2e8cc13b0..32120e7392 100755
--- a/bitbake/bin/bitbake
+++ b/bitbake/bin/bitbake
@@ -263,6 +263,7 @@ def start_server(servermodule, configParams, configuration, features):
logger.handle(event)
raise exc_info[1], None, exc_info[2]
server.detach()
+ cooker.lock.close()
return server
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
index aeb3f71e2f..70cccefe0c 100644
--- a/bitbake/lib/bb/cooker.py
+++ b/bitbake/lib/bb/cooker.py
@@ -38,6 +38,8 @@ import bb, bb.exceptions, bb.command
from bb import utils, data, parse, event, cache, providers, taskdata, runqueue
import Queue
import signal
+import subprocess
+import errno
import prserv.serv
import pyinotify
@@ -1442,6 +1444,33 @@ class BBCooker:
def post_serve(self):
prserv.serv.auto_shutdown(self.data)
bb.event.fire(CookerExit(), self.event_data)
+ lockfile = self.lock.name
+ self.lock.close()
+ self.lock = None
+
+ while not self.lock:
+ with bb.utils.timeout(3):
+ self.lock = bb.utils.lockfile(lockfile, shared=False, retry=False, block=True)
+ if not self.lock:
+ # Some systems may not have lsof available
+ procs = None
+ try:
+ procs = subprocess.check_output(["lsof", '-w', lockfile], stderr=subprocess.STDOUT)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ if procs is None:
+ # Fall back to fuser if lsof is unavailable
+ try:
+ procs = subprocess.check_output(["fuser", '-v', lockfile], stderr=subprocess.STDOUT)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+
+ msg = "Delaying shutdown due to active processes which appear to be holding bitbake.lock"
+ if procs:
+ msg += ":\n%s" % str(procs)
+ print(msg)
def shutdown(self, force = False):
if force:
diff --git a/bitbake/lib/bb/tinfoil.py b/bitbake/lib/bb/tinfoil.py
index 6bcbd47ab3..277131fcf1 100644
--- a/bitbake/lib/bb/tinfoil.py
+++ b/bitbake/lib/bb/tinfoil.py
@@ -84,6 +84,11 @@ class Tinfoil:
else:
self.parseRecipes()
+ def shutdown(self):
+ self.cooker.shutdown(force=True)
+ self.cooker.post_serve()
+ self.cooker.unlockBitbake()
+
class TinfoilConfigParameters(ConfigParameters):
def __init__(self, **options):
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index 9e58b31727..84664551df 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -536,24 +536,29 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if not params.observe_only:
_, error = server.runCommand(["stateForceShutdown"])
main.shutdown = 2
- summary = ""
- if taskfailures:
- summary += pluralise("\nSummary: %s task failed:",
- "\nSummary: %s tasks failed:", len(taskfailures))
- for failure in taskfailures:
- summary += "\n %s" % failure
- if warnings:
- summary += pluralise("\nSummary: There was %s WARNING message shown.",
- "\nSummary: There were %s WARNING messages shown.", warnings)
- if return_value and errors:
- summary += pluralise("\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
- "\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.", errors)
- if summary:
- print(summary)
-
- if interrupted:
- print("Execution was interrupted, returning a non-zero exit code.")
- if return_value == 0:
- return_value = 1
+ try:
+ summary = ""
+ if taskfailures:
+ summary += pluralise("\nSummary: %s task failed:",
+ "\nSummary: %s tasks failed:", len(taskfailures))
+ for failure in taskfailures:
+ summary += "\n %s" % failure
+ if warnings:
+ summary += pluralise("\nSummary: There was %s WARNING message shown.",
+ "\nSummary: There were %s WARNING messages shown.", warnings)
+ if return_value and errors:
+ summary += pluralise("\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
+ "\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.", errors)
+ if summary:
+ print(summary)
+
+ if interrupted:
+ print("Execution was interrupted, returning a non-zero exit code.")
+ if return_value == 0:
+ return_value = 1
+ except IOError as e:
+ import errno
+ if e.errno == errno.EPIPE:
+ pass
return return_value
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py
index 2562db8e47..f217ae366c 100644
--- a/bitbake/lib/bb/utils.py
+++ b/bitbake/lib/bb/utils.py
@@ -31,6 +31,7 @@ import subprocess
import glob
import traceback
import errno
+import signal
from commands import getstatusoutput
from contextlib import contextmanager
@@ -386,10 +387,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)
@@ -402,7 +423,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: