summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2019-12-03 22:01:25 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2020-01-11 11:06:22 +0000
commitcbb463612535f1e87f1314d2fcf927427e81d449 (patch)
tree8ed9f497171273d1b5887ba0cb14fbf01e1fa019 /bitbake
parentafd002529007f1fefc3fc0ed680eb6d4e9494a5d (diff)
downloadpoky-cbb463612535f1e87f1314d2fcf927427e81d449.tar.gz
bitbake: knotty/uihelper: Switch from pids to tids for Task event management
We've seen cases where a task can execute with a given pid, complete and a new task can start using the same pid before the UI handler has had time to adapt. Traceback (most recent call last): File "/home/pokybuild/yocto-worker/qemux86-alt/build/bitbake/lib/bb/ui/knotty.py", line 484, in main helper.eventHandler(event) File "/home/pokybuild/yocto-worker/qemux86-alt/build/bitbake/lib/bb/ui/uihelper.py", line 30, in eventHandler del self.running_tasks[event.pid] KeyError: 13490 This means using pids to match up events on the UI side is a bad idea. Change the code to use task ids instead. There is a small amount of fuzzy matching for the progress information since there is no task information there and we don't want the overhead of a task ID in every event, however since pid reuse is unlikely, we can live with a progress bar not quite working properly in a corner case like this. [YOCTO #13667] (Bitbake rev: a109d034cf4fc059fd5a1e1d03246dac65522dd6) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> (cherry picked from commit e427eafa1bb04008d12100ccc5c862122bba53e0) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/build.py25
-rw-r--r--bitbake/lib/bb/ui/knotty.py12
-rw-r--r--bitbake/lib/bb/ui/uihelper.py39
3 files changed, 43 insertions, 33 deletions
diff --git a/bitbake/lib/bb/build.py b/bitbake/lib/bb/build.py
index 30a2ba236f..3d9cc10c8c 100644
--- a/bitbake/lib/bb/build.py
+++ b/bitbake/lib/bb/build.py
@@ -57,8 +57,9 @@ builtins['os'] = os
57class TaskBase(event.Event): 57class TaskBase(event.Event):
58 """Base class for task events""" 58 """Base class for task events"""
59 59
60 def __init__(self, t, logfile, d): 60 def __init__(self, t, fn, logfile, d):
61 self._task = t 61 self._task = t
62 self._fn = fn
62 self._package = d.getVar("PF") 63 self._package = d.getVar("PF")
63 self._mc = d.getVar("BB_CURRENT_MC") 64 self._mc = d.getVar("BB_CURRENT_MC")
64 self.taskfile = d.getVar("FILE") 65 self.taskfile = d.getVar("FILE")
@@ -81,8 +82,8 @@ class TaskBase(event.Event):
81 82
82class TaskStarted(TaskBase): 83class TaskStarted(TaskBase):
83 """Task execution started""" 84 """Task execution started"""
84 def __init__(self, t, logfile, taskflags, d): 85 def __init__(self, t, fn, logfile, taskflags, d):
85 super(TaskStarted, self).__init__(t, logfile, d) 86 super(TaskStarted, self).__init__(t, fn, logfile, d)
86 self.taskflags = taskflags 87 self.taskflags = taskflags
87 88
88class TaskSucceeded(TaskBase): 89class TaskSucceeded(TaskBase):
@@ -91,9 +92,9 @@ class TaskSucceeded(TaskBase):
91class TaskFailed(TaskBase): 92class TaskFailed(TaskBase):
92 """Task execution failed""" 93 """Task execution failed"""
93 94
94 def __init__(self, task, logfile, metadata, errprinted = False): 95 def __init__(self, task, fn, logfile, metadata, errprinted = False):
95 self.errprinted = errprinted 96 self.errprinted = errprinted
96 super(TaskFailed, self).__init__(task, logfile, metadata) 97 super(TaskFailed, self).__init__(task, fn, logfile, metadata)
97 98
98class TaskFailedSilent(TaskBase): 99class TaskFailedSilent(TaskBase):
99 """Task execution failed (silently)""" 100 """Task execution failed (silently)"""
@@ -103,8 +104,8 @@ class TaskFailedSilent(TaskBase):
103 104
104class TaskInvalid(TaskBase): 105class TaskInvalid(TaskBase):
105 106
106 def __init__(self, task, metadata): 107 def __init__(self, task, fn, metadata):
107 super(TaskInvalid, self).__init__(task, None, metadata) 108 super(TaskInvalid, self).__init__(task, fn, None, metadata)
108 self._message = "No such task '%s'" % task 109 self._message = "No such task '%s'" % task
109 110
110class TaskProgress(event.Event): 111class TaskProgress(event.Event):
@@ -572,7 +573,7 @@ def _exec_task(fn, task, d, quieterr):
572 573
573 try: 574 try:
574 try: 575 try:
575 event.fire(TaskStarted(task, logfn, flags, localdata), localdata) 576 event.fire(TaskStarted(task, fn, logfn, flags, localdata), localdata)
576 except (bb.BBHandledException, SystemExit): 577 except (bb.BBHandledException, SystemExit):
577 return 1 578 return 1
578 579
@@ -583,15 +584,15 @@ def _exec_task(fn, task, d, quieterr):
583 for func in (postfuncs or '').split(): 584 for func in (postfuncs or '').split():
584 exec_func(func, localdata) 585 exec_func(func, localdata)
585 except bb.BBHandledException: 586 except bb.BBHandledException:
586 event.fire(TaskFailed(task, logfn, localdata, True), localdata) 587 event.fire(TaskFailed(task, fn, logfn, localdata, True), localdata)
587 return 1 588 return 1
588 except Exception as exc: 589 except Exception as exc:
589 if quieterr: 590 if quieterr:
590 event.fire(TaskFailedSilent(task, logfn, localdata), localdata) 591 event.fire(TaskFailedSilent(task, fn, logfn, localdata), localdata)
591 else: 592 else:
592 errprinted = errchk.triggered 593 errprinted = errchk.triggered
593 logger.error(str(exc)) 594 logger.error(str(exc))
594 event.fire(TaskFailed(task, logfn, localdata, errprinted), localdata) 595 event.fire(TaskFailed(task, fn, logfn, localdata, errprinted), localdata)
595 return 1 596 return 1
596 finally: 597 finally:
597 sys.stdout.flush() 598 sys.stdout.flush()
@@ -614,7 +615,7 @@ def _exec_task(fn, task, d, quieterr):
614 logger.debug(2, "Zero size logfn %s, removing", logfn) 615 logger.debug(2, "Zero size logfn %s, removing", logfn)
615 bb.utils.remove(logfn) 616 bb.utils.remove(logfn)
616 bb.utils.remove(loglink) 617 bb.utils.remove(loglink)
617 event.fire(TaskSucceeded(task, logfn, localdata), localdata) 618 event.fire(TaskSucceeded(task, fn, logfn, localdata), localdata)
618 619
619 if not localdata.getVarFlag(task, 'nostamp', False) and not localdata.getVarFlag(task, 'selfstamp', False): 620 if not localdata.getVarFlag(task, 'nostamp', False) and not localdata.getVarFlag(task, 'selfstamp', False):
620 make_stamp(task, localdata) 621 make_stamp(task, localdata)
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index 35736ade03..bd9911cf6f 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -255,19 +255,19 @@ class TerminalFilter(object):
255 start_time = activetasks[t].get("starttime", None) 255 start_time = activetasks[t].get("starttime", None)
256 if not pbar or pbar.bouncing != (progress < 0): 256 if not pbar or pbar.bouncing != (progress < 0):
257 if progress < 0: 257 if progress < 0:
258 pbar = BBProgress("0: %s (pid %s) " % (activetasks[t]["title"], t), 100, widgets=[progressbar.BouncingSlider(), ''], extrapos=2, resize_handler=self.sigwinch_handle) 258 pbar = BBProgress("0: %s (pid %s) " % (activetasks[t]["title"], activetasks[t]["pid"]), 100, widgets=[progressbar.BouncingSlider(), ''], extrapos=2, resize_handler=self.sigwinch_handle)
259 pbar.bouncing = True 259 pbar.bouncing = True
260 else: 260 else:
261 pbar = BBProgress("0: %s (pid %s) " % (activetasks[t]["title"], t), 100, widgets=[progressbar.Percentage(), ' ', progressbar.Bar(), ''], extrapos=4, resize_handler=self.sigwinch_handle) 261 pbar = BBProgress("0: %s (pid %s) " % (activetasks[t]["title"], activetasks[t]["pid"]), 100, widgets=[progressbar.Percentage(), ' ', progressbar.Bar(), ''], extrapos=4, resize_handler=self.sigwinch_handle)
262 pbar.bouncing = False 262 pbar.bouncing = False
263 activetasks[t]["progressbar"] = pbar 263 activetasks[t]["progressbar"] = pbar
264 tasks.append((pbar, progress, rate, start_time)) 264 tasks.append((pbar, progress, rate, start_time))
265 else: 265 else:
266 start_time = activetasks[t].get("starttime", None) 266 start_time = activetasks[t].get("starttime", None)
267 if start_time: 267 if start_time:
268 tasks.append("%s - %s (pid %s)" % (activetasks[t]["title"], self.elapsed(currenttime - start_time), t)) 268 tasks.append("%s - %s (pid %s)" % (activetasks[t]["title"], self.elapsed(currenttime - start_time), activetasks[t]["pid"]))
269 else: 269 else:
270 tasks.append("%s (pid %s)" % (activetasks[t]["title"], t)) 270 tasks.append("%s (pid %s)" % (activetasks[t]["title"], activetasks[t]["pid"]))
271 271
272 if self.main.shutdown: 272 if self.main.shutdown:
273 content = "Waiting for %s running tasks to finish:" % len(activetasks) 273 content = "Waiting for %s running tasks to finish:" % len(activetasks)
@@ -517,8 +517,8 @@ def main(server, eventHandler, params, tf = TerminalFilter):
517 continue 517 continue
518 518
519 # Prefix task messages with recipe/task 519 # Prefix task messages with recipe/task
520 if event.taskpid in helper.running_tasks and event.levelno != format.PLAIN: 520 if event.taskpid in helper.pidmap and event.levelno != format.PLAIN:
521 taskinfo = helper.running_tasks[event.taskpid] 521 taskinfo = helper.running_tasks[helper.pidmap[event.taskpid]]
522 event.msg = taskinfo['title'] + ': ' + event.msg 522 event.msg = taskinfo['title'] + ': ' + event.msg
523 if hasattr(event, 'fn'): 523 if hasattr(event, 'fn'):
524 event.msg = event.fn + ': ' + event.msg 524 event.msg = event.fn + ': ' + event.msg
diff --git a/bitbake/lib/bb/ui/uihelper.py b/bitbake/lib/bb/ui/uihelper.py
index c8dd7df087..48d808ae28 100644
--- a/bitbake/lib/bb/ui/uihelper.py
+++ b/bitbake/lib/bb/ui/uihelper.py
@@ -15,39 +15,48 @@ class BBUIHelper:
15 # Running PIDs preserves the order tasks were executed in 15 # Running PIDs preserves the order tasks were executed in
16 self.running_pids = [] 16 self.running_pids = []
17 self.failed_tasks = [] 17 self.failed_tasks = []
18 self.pidmap = {}
18 self.tasknumber_current = 0 19 self.tasknumber_current = 0
19 self.tasknumber_total = 0 20 self.tasknumber_total = 0
20 21
21 def eventHandler(self, event): 22 def eventHandler(self, event):
23 # PIDs are a bad idea as they can be reused before we process all UI events.
24 # We maintain a 'fuzzy' match for TaskProgress since there is no other way to match
25 def removetid(pid, tid):
26 self.running_pids.remove(tid)
27 del self.running_tasks[tid]
28 if self.pidmap[pid] == tid:
29 del self.pidmap[pid]
30 self.needUpdate = True
31
22 if isinstance(event, bb.build.TaskStarted): 32 if isinstance(event, bb.build.TaskStarted):
33 tid = event._fn + ":" + event._task
23 if event._mc != "default": 34 if event._mc != "default":
24 self.running_tasks[event.pid] = { 'title' : "mc:%s:%s %s" % (event._mc, event._package, event._task), 'starttime' : time.time() } 35 self.running_tasks[tid] = { 'title' : "mc:%s:%s %s" % (event._mc, event._package, event._task), 'starttime' : time.time(), 'pid' : event.pid }
25 else: 36 else:
26 self.running_tasks[event.pid] = { 'title' : "%s %s" % (event._package, event._task), 'starttime' : time.time() } 37 self.running_tasks[tid] = { 'title' : "%s %s" % (event._package, event._task), 'starttime' : time.time(), 'pid' : event.pid }
27 self.running_pids.append(event.pid) 38 self.running_pids.append(tid)
39 self.pidmap[event.pid] = tid
28 self.needUpdate = True 40 self.needUpdate = True
29 elif isinstance(event, bb.build.TaskSucceeded): 41 elif isinstance(event, bb.build.TaskSucceeded):
30 del self.running_tasks[event.pid] 42 tid = event._fn + ":" + event._task
31 self.running_pids.remove(event.pid) 43 removetid(event.pid, tid)
32 self.needUpdate = True
33 elif isinstance(event, bb.build.TaskFailedSilent): 44 elif isinstance(event, bb.build.TaskFailedSilent):
34 del self.running_tasks[event.pid] 45 tid = event._fn + ":" + event._task
35 self.running_pids.remove(event.pid) 46 removetid(event.pid, tid)
36 # Don't add to the failed tasks list since this is e.g. a setscene task failure 47 # Don't add to the failed tasks list since this is e.g. a setscene task failure
37 self.needUpdate = True
38 elif isinstance(event, bb.build.TaskFailed): 48 elif isinstance(event, bb.build.TaskFailed):
39 del self.running_tasks[event.pid] 49 tid = event._fn + ":" + event._task
40 self.running_pids.remove(event.pid) 50 removetid(event.pid, tid)
41 self.failed_tasks.append( { 'title' : "%s %s" % (event._package, event._task)}) 51 self.failed_tasks.append( { 'title' : "%s %s" % (event._package, event._task)})
42 self.needUpdate = True
43 elif isinstance(event, bb.runqueue.runQueueTaskStarted): 52 elif isinstance(event, bb.runqueue.runQueueTaskStarted):
44 self.tasknumber_current = event.stats.completed + event.stats.active + event.stats.failed + 1 53 self.tasknumber_current = event.stats.completed + event.stats.active + event.stats.failed + 1
45 self.tasknumber_total = event.stats.total 54 self.tasknumber_total = event.stats.total
46 self.needUpdate = True 55 self.needUpdate = True
47 elif isinstance(event, bb.build.TaskProgress): 56 elif isinstance(event, bb.build.TaskProgress):
48 if event.pid > 0: 57 if event.pid > 0 and event.pid in self.pidmap:
49 self.running_tasks[event.pid]['progress'] = event.progress 58 self.running_tasks[self.pidmap[event.pid]]['progress'] = event.progress
50 self.running_tasks[event.pid]['rate'] = event.rate 59 self.running_tasks[self.pidmap[event.pid]]['rate'] = event.rate
51 self.needUpdate = True 60 self.needUpdate = True
52 else: 61 else:
53 return False 62 return False