@@ -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 == "":
@@ -1502,23 +1502,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
@@ -1548,8 +1546,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:
@@ -1557,8 +1554,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
@@ -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"
@@ -364,6 +368,10 @@ class ProcessServer():
for function, data in list(self._idlefuns.items()):
try:
retval = function(self, data, False)
+ if isinstance(retval, idleFinish):
+ del self._idlefuns[function]
+ self.cooker.command.finishAsyncCommand(retval.msg)
+ nextsleep = None
if retval is False:
del self._idlefuns[function]
nextsleep = None
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> --- lib/bb/command.py | 13 +++++-------- lib/bb/cooker.py | 13 +++++-------- lib/bb/server/process.py | 8 ++++++++ 3 files changed, 18 insertions(+), 16 deletions(-)