summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2025-07-02 17:55:13 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2025-07-07 22:13:14 +0100
commita8b57414cfd14ad520588835f431a94106202a5a (patch)
tree3f95fc62e9d17b605c65a7857bb7bb4013b03473 /bitbake
parent3350021579e1ed92e1c9107e9e6b282786366cdf (diff)
downloadpoky-a8b57414cfd14ad520588835f431a94106202a5a.tar.gz
bitbake: cooker: Try and avoid parsing hangs
We sometimes see hangs in parsing during automated testing. It appears that SIGINT was sent to the underlying processes which see KeyboardInterrupt but they're stuck trying to write into the results pipe. The SIGINT was probably from some kind of parsing failure which doens't happen often, hence the hang being rare (in the incompatible license selftests from OE). This patch: * sets a flag to indicate exit upon SIGINT so the exit is more graceful and a defined exit path * empties the results queue after we send the quit event * empties the results queue after the SIGINT for good measure * increases the 0.5s timeout to 2s since we now have some very slow to parse recipes due to class extensions (ptests) This should hopefully make the parsing failure codepaths more robust. (Bitbake rev: 5b533370595f83b87e480bace3e0b42c9ba61e22) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/cooker.py24
1 files changed, 15 insertions, 9 deletions
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
index 1810bcc604..91e3ee025e 100644
--- a/bitbake/lib/bb/cooker.py
+++ b/bitbake/lib/bb/cooker.py
@@ -2009,6 +2009,7 @@ class Parser(multiprocessing.Process):
2009 self.queue_signals = False 2009 self.queue_signals = False
2010 self.signal_received = [] 2010 self.signal_received = []
2011 self.signal_threadlock = threading.Lock() 2011 self.signal_threadlock = threading.Lock()
2012 self.exit = False
2012 2013
2013 def catch_sig(self, signum, frame): 2014 def catch_sig(self, signum, frame):
2014 if self.queue_signals: 2015 if self.queue_signals:
@@ -2021,7 +2022,7 @@ class Parser(multiprocessing.Process):
2021 signal.signal(signal.SIGTERM, signal.SIG_DFL) 2022 signal.signal(signal.SIGTERM, signal.SIG_DFL)
2022 os.kill(os.getpid(), signal.SIGTERM) 2023 os.kill(os.getpid(), signal.SIGTERM)
2023 elif signum == signal.SIGINT: 2024 elif signum == signal.SIGINT:
2024 signal.default_int_handler(signum, frame) 2025 self.exit = True
2025 2026
2026 def run(self): 2027 def run(self):
2027 2028
@@ -2059,7 +2060,7 @@ class Parser(multiprocessing.Process):
2059 pending = [] 2060 pending = []
2060 havejobs = True 2061 havejobs = True
2061 try: 2062 try:
2062 while havejobs or pending: 2063 while (havejobs or pending) and not self.exit:
2063 if self.quit.is_set(): 2064 if self.quit.is_set():
2064 break 2065 break
2065 2066
@@ -2196,11 +2197,12 @@ class CookerParser(object):
2196 2197
2197 # Cleanup the queue before call process.join(), otherwise there might be 2198 # Cleanup the queue before call process.join(), otherwise there might be
2198 # deadlocks. 2199 # deadlocks.
2199 while True: 2200 def read_results():
2200 try: 2201 while True:
2201 self.result_queue.get(timeout=0.25) 2202 try:
2202 except queue.Empty: 2203 self.result_queue.get(timeout=0.25)
2203 break 2204 except queue.Empty:
2205 break
2204 2206
2205 def sync_caches(): 2207 def sync_caches():
2206 for c in self.bb_caches.values(): 2208 for c in self.bb_caches.values():
@@ -2212,15 +2214,19 @@ class CookerParser(object):
2212 2214
2213 self.parser_quit.set() 2215 self.parser_quit.set()
2214 2216
2217 read_results()
2218
2215 for process in self.processes: 2219 for process in self.processes:
2216 process.join(0.5) 2220 process.join(2)
2217 2221
2218 for process in self.processes: 2222 for process in self.processes:
2219 if process.exitcode is None: 2223 if process.exitcode is None:
2220 os.kill(process.pid, signal.SIGINT) 2224 os.kill(process.pid, signal.SIGINT)
2221 2225
2226 read_results()
2227
2222 for process in self.processes: 2228 for process in self.processes:
2223 process.join(0.5) 2229 process.join(2)
2224 2230
2225 for process in self.processes: 2231 for process in self.processes:
2226 if process.exitcode is None: 2232 if process.exitcode is None: