diff options
| -rw-r--r-- | bitbake/lib/bb/command.py | 6 | ||||
| -rw-r--r-- | bitbake/lib/bb/cooker.py | 30 | ||||
| -rwxr-xr-x | bitbake/lib/bb/main.py | 1 | ||||
| -rw-r--r-- | bitbake/lib/bb/tinfoil.py | 1 | ||||
| -rw-r--r-- | bitbake/lib/bb/ui/knotty.py | 20 | ||||
| -rw-r--r-- | bitbake/lib/bb/utils.py | 29 |
6 files changed, 57 insertions, 30 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py index 2b02584b5e..24ff341045 100644 --- a/bitbake/lib/bb/command.py +++ b/bitbake/lib/bb/command.py | |||
| @@ -267,12 +267,6 @@ class CommandsSync: | |||
| 267 | features = params[0] | 267 | features = params[0] |
| 268 | command.cooker.setFeatures(features) | 268 | command.cooker.setFeatures(features) |
| 269 | 269 | ||
| 270 | def unlockBitbake(self, command, params): | ||
| 271 | """ | ||
| 272 | Unlock bitbake.lock file | ||
| 273 | """ | ||
| 274 | command.cooker.unlockBitbake() | ||
| 275 | |||
| 276 | # although we change the internal state of the cooker, this is transparent since | 270 | # although we change the internal state of the cooker, this is transparent since |
| 277 | # we always take and leave the cooker in state.initial | 271 | # we always take and leave the cooker in state.initial |
| 278 | setFeatures.readonly = True | 272 | setFeatures.readonly = True |
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py index 46e5560e83..52b81be7b6 100644 --- a/bitbake/lib/bb/cooker.py +++ b/bitbake/lib/bb/cooker.py | |||
| @@ -38,6 +38,8 @@ import bb, bb.exceptions, bb.command | |||
| 38 | from bb import utils, data, parse, event, cache, providers, taskdata, runqueue, build | 38 | from bb import utils, data, parse, event, cache, providers, taskdata, runqueue, build |
| 39 | import Queue | 39 | import Queue |
| 40 | import signal | 40 | import signal |
| 41 | import subprocess | ||
| 42 | import errno | ||
| 41 | import prserv.serv | 43 | import prserv.serv |
| 42 | import pyinotify | 44 | import pyinotify |
| 43 | 45 | ||
| @@ -1532,6 +1534,34 @@ class BBCooker: | |||
| 1532 | def post_serve(self): | 1534 | def post_serve(self): |
| 1533 | prserv.serv.auto_shutdown(self.data) | 1535 | prserv.serv.auto_shutdown(self.data) |
| 1534 | bb.event.fire(CookerExit(), self.expanded_data) | 1536 | bb.event.fire(CookerExit(), self.expanded_data) |
| 1537 | lockfile = self.lock.name | ||
| 1538 | self.lock.close() | ||
| 1539 | self.lock = None | ||
| 1540 | |||
| 1541 | while not self.lock: | ||
| 1542 | with bb.utils.timeout(3): | ||
| 1543 | self.lock = bb.utils.lockfile(lockfile, shared=False, retry=False, block=True) | ||
| 1544 | if not self.lock: | ||
| 1545 | # Some systems may not have lsof available | ||
| 1546 | procs = None | ||
| 1547 | try: | ||
| 1548 | procs = subprocess.check_output(["lsof", '-w', lockfile], stderr=subprocess.STDOUT) | ||
| 1549 | except OSError as e: | ||
| 1550 | if e.errno != errno.ENOENT: | ||
| 1551 | raise | ||
| 1552 | if procs is None: | ||
| 1553 | # Fall back to fuser if lsof is unavailable | ||
| 1554 | try: | ||
| 1555 | procs = subprocess.check_output(["fuser", '-v', lockfile], stderr=subprocess.STDOUT) | ||
| 1556 | except OSError as e: | ||
| 1557 | if e.errno != errno.ENOENT: | ||
| 1558 | raise | ||
| 1559 | |||
| 1560 | msg = "Delaying shutdown due to active processes which appear to be holding bitbake.lock" | ||
| 1561 | if procs: | ||
| 1562 | msg += ":\n%s" % str(procs) | ||
| 1563 | print(msg) | ||
| 1564 | |||
| 1535 | 1565 | ||
| 1536 | def shutdown(self, force = False): | 1566 | def shutdown(self, force = False): |
| 1537 | if force: | 1567 | if force: |
diff --git a/bitbake/lib/bb/main.py b/bitbake/lib/bb/main.py index ee72328f4e..f08a8ef592 100755 --- a/bitbake/lib/bb/main.py +++ b/bitbake/lib/bb/main.py | |||
| @@ -257,6 +257,7 @@ def start_server(servermodule, configParams, configuration, features): | |||
| 257 | logger.handle(event) | 257 | logger.handle(event) |
| 258 | raise exc_info[1], None, exc_info[2] | 258 | raise exc_info[1], None, exc_info[2] |
| 259 | server.detach() | 259 | server.detach() |
| 260 | cooker.lock.close() | ||
| 260 | return server | 261 | return server |
| 261 | 262 | ||
| 262 | 263 | ||
diff --git a/bitbake/lib/bb/tinfoil.py b/bitbake/lib/bb/tinfoil.py index 3095c20493..1ea46d8eec 100644 --- a/bitbake/lib/bb/tinfoil.py +++ b/bitbake/lib/bb/tinfoil.py | |||
| @@ -86,6 +86,7 @@ class Tinfoil: | |||
| 86 | 86 | ||
| 87 | def shutdown(self): | 87 | def shutdown(self): |
| 88 | self.cooker.shutdown(force=True) | 88 | self.cooker.shutdown(force=True) |
| 89 | self.cooker.post_serve() | ||
| 89 | self.cooker.unlockBitbake() | 90 | self.cooker.unlockBitbake() |
| 90 | 91 | ||
| 91 | class TinfoilConfigParameters(ConfigParameters): | 92 | class TinfoilConfigParameters(ConfigParameters): |
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py index 9788a9287c..2bee242eb0 100644 --- a/bitbake/lib/bb/ui/knotty.py +++ b/bitbake/lib/bb/ui/knotty.py | |||
| @@ -310,7 +310,6 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
| 310 | errors = 0 | 310 | errors = 0 |
| 311 | warnings = 0 | 311 | warnings = 0 |
| 312 | taskfailures = [] | 312 | taskfailures = [] |
| 313 | locktries = 10 | ||
| 314 | 313 | ||
| 315 | termfilter = tf(main, helper, console, errconsole, format) | 314 | termfilter = tf(main, helper, console, errconsole, format) |
| 316 | atexit.register(termfilter.finish) | 315 | atexit.register(termfilter.finish) |
| @@ -538,25 +537,6 @@ def main(server, eventHandler, params, tf = TerminalFilter): | |||
| 538 | _, error = server.runCommand(["stateForceShutdown"]) | 537 | _, error = server.runCommand(["stateForceShutdown"]) |
| 539 | main.shutdown = 2 | 538 | main.shutdown = 2 |
| 540 | try: | 539 | try: |
| 541 | topdir, error = server.runCommand(["getVariable", "TOPDIR"]) | ||
| 542 | if error: | ||
| 543 | logger.warn("Unable to get the value of TOPDIR variable: %s" % error) | ||
| 544 | else: | ||
| 545 | lockfile = "%s/bitbake.lock" % topdir | ||
| 546 | _, error = server.runCommand(["unlockBitbake"]) | ||
| 547 | if error: | ||
| 548 | logger.warn("Unable to unlock the file %s" % lockfile) | ||
| 549 | else: | ||
| 550 | while locktries: | ||
| 551 | lf = bb.utils.lockfile(lockfile, False, False) | ||
| 552 | if not lf: | ||
| 553 | time.sleep(1) | ||
| 554 | locktries -=1 | ||
| 555 | else: | ||
| 556 | bb.utils.unlockfile(lf) | ||
| 557 | break | ||
| 558 | if not locktries: | ||
| 559 | logger.warn("Knotty could not lock the file ${TOPDIR}/bitbake.lock, probably locked by cooker and not unlocked yet. Immediate bitbake commands may failed") | ||
| 560 | summary = "" | 540 | summary = "" |
| 561 | if taskfailures: | 541 | if taskfailures: |
| 562 | summary += pluralise("\nSummary: %s task failed:", | 542 | summary += pluralise("\nSummary: %s task failed:", |
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py index 857f5bcf96..607ffc5065 100644 --- a/bitbake/lib/bb/utils.py +++ b/bitbake/lib/bb/utils.py | |||
| @@ -31,6 +31,7 @@ import subprocess | |||
| 31 | import glob | 31 | import glob |
| 32 | import traceback | 32 | import traceback |
| 33 | import errno | 33 | import errno |
| 34 | import signal | ||
| 34 | from commands import getstatusoutput | 35 | from commands import getstatusoutput |
| 35 | from contextlib import contextmanager | 36 | from contextlib import contextmanager |
| 36 | 37 | ||
| @@ -412,10 +413,30 @@ def fileslocked(files): | |||
| 412 | for lock in locks: | 413 | for lock in locks: |
| 413 | bb.utils.unlockfile(lock) | 414 | bb.utils.unlockfile(lock) |
| 414 | 415 | ||
| 415 | def lockfile(name, shared=False, retry=True): | 416 | @contextmanager |
| 417 | def timeout(seconds): | ||
| 418 | def timeout_handler(signum, frame): | ||
| 419 | pass | ||
| 420 | |||
| 421 | original_handler = signal.signal(signal.SIGALRM, timeout_handler) | ||
| 422 | |||
| 423 | try: | ||
| 424 | signal.alarm(seconds) | ||
| 425 | yield | ||
| 426 | finally: | ||
| 427 | signal.alarm(0) | ||
| 428 | signal.signal(signal.SIGALRM, original_handler) | ||
| 429 | |||
| 430 | def lockfile(name, shared=False, retry=True, block=False): | ||
| 416 | """ | 431 | """ |
| 417 | Use the file fn as a lock file, return when the lock has been acquired. | 432 | Use the specified file as a lock file, return when the lock has |
| 418 | Returns a variable to pass to unlockfile(). | 433 | been acquired. Returns a variable to pass to unlockfile(). |
| 434 | Parameters: | ||
| 435 | retry: True to re-try locking if it fails, False otherwise | ||
| 436 | block: True to block until the lock succeeds, False otherwise | ||
| 437 | The retry and block parameters are kind of equivalent unless you | ||
| 438 | consider the possibility of sending a signal to the process to break | ||
| 439 | out - at which point you want block=True rather than retry=True. | ||
| 419 | """ | 440 | """ |
| 420 | dirname = os.path.dirname(name) | 441 | dirname = os.path.dirname(name) |
| 421 | mkdirhier(dirname) | 442 | mkdirhier(dirname) |
| @@ -428,7 +449,7 @@ def lockfile(name, shared=False, retry=True): | |||
| 428 | op = fcntl.LOCK_EX | 449 | op = fcntl.LOCK_EX |
| 429 | if shared: | 450 | if shared: |
| 430 | op = fcntl.LOCK_SH | 451 | op = fcntl.LOCK_SH |
| 431 | if not retry: | 452 | if not retry and not block: |
| 432 | op = op | fcntl.LOCK_NB | 453 | op = op | fcntl.LOCK_NB |
| 433 | 454 | ||
| 434 | while True: | 455 | while True: |
