From 8b792d4f75b451f9e08fdb13464a0b66c11bc075 Mon Sep 17 00:00:00 2001 From: Tomasz Dziendzielski Date: Wed, 10 Feb 2021 12:15:15 +0100 Subject: bitbake: event: Prevent bitbake from executing event handler for wrong multiconfig target When multiconfig is used bitbake might try to run events that don't exist for specific mc target. In cooker.py we pass `self.databuilder.mcdata[mc]` data that contains names of events' handlers per mc target, but fire_class_handlers uses global _handlers variable that is created during parsing of all the targets. This leads to a problem where bitbake runs event handler that don't exist for a target or even overrides them - if multiple targets use event handler with the same name but different code then only one version will be executed for all targets. See [YOCTO #13071] for detailed bug information. Add mc target name as a prefix to event handler name so there won't be two different handlers with the same name. Add internal __BBHANDLERS_MC variable to have the handlers lists per machine. (Bitbake rev: 5f7fdf7b2d8c59805c8ef4dae84f536baa5e172b) Signed-off-by: Tomasz Dziendzielski Signed-off-by: Richard Purdie --- bitbake/lib/bb/cookerdata.py | 2 +- bitbake/lib/bb/event.py | 26 ++++++++++++++++++++++++-- bitbake/lib/bb/parse/ast.py | 2 +- bitbake/lib/bb/runqueue.py | 4 ++-- 4 files changed, 28 insertions(+), 6 deletions(-) (limited to 'bitbake') diff --git a/bitbake/lib/bb/cookerdata.py b/bitbake/lib/bb/cookerdata.py index c39b568130..1c1e008c6b 100644 --- a/bitbake/lib/bb/cookerdata.py +++ b/bitbake/lib/bb/cookerdata.py @@ -429,7 +429,7 @@ class CookerDataBuilder(object): parselog.critical("Undefined event handler function '%s'" % var) raise bb.BBHandledException() handlerln = int(data.getVarFlag(var, "lineno", False)) - bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln) + bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data) data.setVar('BBINCLUDED',bb.parse.get_file_depends(data)) diff --git a/bitbake/lib/bb/event.py b/bitbake/lib/bb/event.py index 694b470520..ff89959460 100644 --- a/bitbake/lib/bb/event.py +++ b/bitbake/lib/bb/event.py @@ -118,6 +118,8 @@ def fire_class_handlers(event, d): if _eventfilter: if not _eventfilter(name, handler, event, d): continue + if d and not name in (d.getVar("__BBHANDLERS_MC") or []): + continue execute_handler(name, handler, event, d) ui_queue = [] @@ -227,9 +229,13 @@ def fire_from_worker(event, d): fire_ui_handlers(event, d) noop = lambda _: None -def register(name, handler, mask=None, filename=None, lineno=None): +def register(name, handler, mask=None, filename=None, lineno=None, data=None): """Register an Event handler""" + if data and data.getVar("BB_CURRENT_MC"): + mc = data.getVar("BB_CURRENT_MC") + name = '%s%s' % (mc, name) + # already registered if name in _handlers: return AlreadyRegistered @@ -268,10 +274,20 @@ def register(name, handler, mask=None, filename=None, lineno=None): _event_handler_map[m] = {} _event_handler_map[m][name] = True + if data: + bbhands_mc = (data.getVar("__BBHANDLERS_MC") or []) + bbhands_mc.append(name) + data.setVar("__BBHANDLERS_MC", bbhands_mc) + return Registered -def remove(name, handler): +def remove(name, handler, data=None): """Remove an Event handler""" + if data: + if data.getVar("BB_CURRENT_MC"): + mc = data.getVar("BB_CURRENT_MC") + name = '%s%s' % (mc, name) + _handlers.pop(name) if name in _catchall_handlers: _catchall_handlers.pop(name) @@ -279,6 +295,12 @@ def remove(name, handler): if name in _event_handler_map[event]: _event_handler_map[event].pop(name) + if data: + bbhands_mc = (data.getVar("__BBHANDLERS_MC") or []) + if name in bbhands_mc: + bbhands_mc.remove(name) + data.setVar("__BBHANDLERS_MC", bbhands_mc) + def get_handlers(): return _handlers diff --git a/bitbake/lib/bb/parse/ast.py b/bitbake/lib/bb/parse/ast.py index 0596993d01..50a88f7da7 100644 --- a/bitbake/lib/bb/parse/ast.py +++ b/bitbake/lib/bb/parse/ast.py @@ -335,7 +335,7 @@ def finalize(fn, d, variant = None): if not handlerfn: bb.fatal("Undefined event handler function '%s'" % var) handlerln = int(d.getVarFlag(var, "lineno", False)) - bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln) + bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data=d) bb.event.fire(bb.event.RecipePreFinalise(fn), d) diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py index 2f521e5a14..b8b217c64a 100644 --- a/bitbake/lib/bb/runqueue.py +++ b/bitbake/lib/bb/runqueue.py @@ -1466,7 +1466,7 @@ class RunQueue: if not self.dm_event_handler_registered: res = bb.event.register(self.dm_event_handler_name, lambda x: self.dm.check(self) if self.state in [runQueueRunning, runQueueCleanUp] else False, - ('bb.event.HeartbeatEvent',)) + ('bb.event.HeartbeatEvent',), data=self.cfgData) self.dm_event_handler_registered = True dump = self.cooker.configuration.dump_signatures @@ -1505,7 +1505,7 @@ class RunQueue: build_done = self.state is runQueueComplete or self.state is runQueueFailed if build_done and self.dm_event_handler_registered: - bb.event.remove(self.dm_event_handler_name, None) + bb.event.remove(self.dm_event_handler_name, None, data=self.cfgData) self.dm_event_handler_registered = False if build_done and self.rqexe: -- cgit v1.2.3-54-g00ecf