aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2022-12-29 14:56:14 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-12-30 22:00:32 +0000
commit102e8d0d4c5c0dd8c7ba09ad26589deec77e4308 (patch)
treeb140835614fbc4cad919bc29c021f7bed88df83c
parent6569ab64bea35de21acc89053ba76e2828163f3f (diff)
downloadbitbake-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.py13
-rw-r--r--lib/bb/cooker.py13
-rw-r--r--lib/bb/server/process.py11
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