bitbake: 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.

(Bitbake rev: 102e8d0d4c5c0dd8c7ba09ad26589deec77e4308)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Richard Purdie
2022-12-29 14:56:14 +00:00
parent ff2d778f6d
commit c4ecfc4dc5
3 changed files with 20 additions and 17 deletions

View File

@@ -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 == "":

View File

@@ -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

View File

@@ -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