diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-12-29 14:56:14 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-12-30 22:00:32 +0000 |
commit | 102e8d0d4c5c0dd8c7ba09ad26589deec77e4308 (patch) | |
tree | b140835614fbc4cad919bc29c021f7bed88df83c | |
parent | 6569ab64bea35de21acc89053ba76e2828163f3f (diff) | |
download | bitbake-102e8d0d4c5c0dd8c7ba09ad26589deec77e4308.tar.gz |
server/process: Improve idle loop exit code
When idle handlers want to exit, returning "False" isn't very clear
and also causes challenges with the ordering of the removing the idle
handler and marking that no async command is running.
Use a specific class to signal the exit condition allowing clearer code
and allowing the async command to be cleared after the handler has been
removed, reducing any opportunity for races.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | lib/bb/command.py | 13 | ||||
-rw-r--r-- | lib/bb/cooker.py | 13 | ||||
-rw-r--r-- | lib/bb/server/process.py | 11 |
3 files changed, 20 insertions, 17 deletions
diff --git a/lib/bb/command.py b/lib/bb/command.py index cbac07f51..732327d84 100644 --- a/lib/bb/command.py +++ b/lib/bb/command.py @@ -128,22 +128,19 @@ class Command: else: return False except KeyboardInterrupt as exc: - self.finishAsyncCommand("Interrupted") - return False + return bb.server.process.idleFinish("Interrupted") except SystemExit as exc: arg = exc.args[0] if isinstance(arg, str): - self.finishAsyncCommand(arg) + return bb.server.process.idleFinish(arg) else: - self.finishAsyncCommand("Exited with %s" % arg) - return False + return bb.server.process.idleFinish("Exited with %s" % arg) except Exception as exc: import traceback if isinstance(exc, bb.BBHandledException): - self.finishAsyncCommand("") + return bb.server.process.idleFinish("") else: - self.finishAsyncCommand(traceback.format_exc()) - return False + return bb.server.process.idleFinish(traceback.format_exc()) def finishAsyncCommand(self, msg=None, code=None): if msg or msg == "": diff --git a/lib/bb/cooker.py b/lib/bb/cooker.py index adc232e28..ded936978 100644 --- a/lib/bb/cooker.py +++ b/lib/bb/cooker.py @@ -1489,23 +1489,21 @@ class BBCooker: failures += len(exc.args) retval = False except SystemExit as exc: - self.command.finishAsyncCommand(str(exc)) if quietlog: bb.runqueue.logger.setLevel(rqloglevel) - return False + return bb.server.process.idleFinish(str(exc)) if not retval: if fireevents: bb.event.fire(bb.event.BuildCompleted(len(rq.rqdata.runtaskentries), buildname, item, failures, interrupted), self.databuilder.mcdata[mc]) bb.event.disable_heartbeat() - self.command.finishAsyncCommand(msg) # We trashed self.recipecaches above self.parsecache_valid = False self.configuration.limited_deps = False bb.parse.siggen.reset(self.data) if quietlog: bb.runqueue.logger.setLevel(rqloglevel) - return False + return bb.server.process.idleFinish(msg) if retval is True: return True return retval @@ -1535,8 +1533,7 @@ class BBCooker: failures += len(exc.args) retval = False except SystemExit as exc: - self.command.finishAsyncCommand(str(exc)) - return False + return bb.server.process.idleFinish(str(exc)) if not retval: try: @@ -1544,8 +1541,8 @@ class BBCooker: bb.event.fire(bb.event.BuildCompleted(len(rq.rqdata.runtaskentries), buildname, targets, failures, interrupted), self.databuilder.mcdata[mc]) finally: bb.event.disable_heartbeat() - self.command.finishAsyncCommand(msg) - return False + return bb.server.process.idleFinish(msg) + if retval is True: return True return retval diff --git a/lib/bb/server/process.py b/lib/bb/server/process.py index eba28ad98..5acc105e0 100644 --- a/lib/bb/server/process.py +++ b/lib/bb/server/process.py @@ -71,6 +71,10 @@ def get_lockfile_process_msg(lockfile): return procs.decode("utf-8") return None +class idleFinish(): + def __init__(self, msg): + self.msg = msg + class ProcessServer(): profile_filename = "profile.log" profile_processed_filename = "profile.log.processed" @@ -361,7 +365,12 @@ class ProcessServer(): for function, data in list(self._idlefuns.items()): try: retval = function(self, data, False) - if retval is False: + if isinstance(retval, idleFinish): + serverlog("Removing idle function %s at idleFinish" % str(function)) + del self._idlefuns[function] + self.cooker.command.finishAsyncCommand(retval.msg) + nextsleep = None + elif retval is False: serverlog("Removing idle function %s" % str(function)) del self._idlefuns[function] nextsleep = None |