diff mbox series

[06/15] server/process: Improve idle loop exit code

Message ID 20221229170728.880367-7-richard.purdie@linuxfoundation.org
State Accepted, archived
Commit 102e8d0d4c5c0dd8c7ba09ad26589deec77e4308
Headers show
Series Bitbake server thread enabling | expand

Commit Message

Richard Purdie Dec. 29, 2022, 5:07 p.m. UTC
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(-)
diff mbox series

Patch

diff --git a/lib/bb/command.py b/lib/bb/command.py
index d2c01bf743..d03f35a896 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 33e87981c5..5e18c85bb8 100644
--- a/lib/bb/cooker.py
+++ b/lib/bb/cooker.py
@@ -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
diff --git a/lib/bb/server/process.py b/lib/bb/server/process.py
index 6f43330fae..3c909942aa 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"
@@ -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