All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5] event: Prevent bitbake from executing event handler for wrong multiconfig target
@ 2021-02-10 11:15 Tomasz Dziendzielski
  2021-02-16 12:39 ` [bitbake-devel] " Richard Purdie
  2021-03-05 23:37 ` Richard Purdie
  0 siblings, 2 replies; 5+ messages in thread
From: Tomasz Dziendzielski @ 2021-02-10 11:15 UTC (permalink / raw)
  To: bitbake-devel; +Cc: Tomasz Dziendzielski

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.

Signed-off-by: Tomasz Dziendzielski <tomasz.dziendzielski@gmail.com>

--- v5 move the whole logic to event.bb, fix tests
---
 lib/bb/cookerdata.py |  2 +-
 lib/bb/event.py      | 26 ++++++++++++++++++++++++--
 lib/bb/parse/ast.py  |  2 +-
 lib/bb/runqueue.py   |  4 ++--
 4 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/lib/bb/cookerdata.py b/lib/bb/cookerdata.py
index c39b5681..1c1e008c 100644
--- a/lib/bb/cookerdata.py
+++ b/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/lib/bb/event.py b/lib/bb/event.py
index 694b4705..ff899594 100644
--- a/lib/bb/event.py
+++ b/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/lib/bb/parse/ast.py b/lib/bb/parse/ast.py
index 0714296a..dc1d7643 100644
--- a/lib/bb/parse/ast.py
+++ b/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/lib/bb/runqueue.py b/lib/bb/runqueue.py
index 7d493eb4..fe4deb19 100644
--- a/lib/bb/runqueue.py
+++ b/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:
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [bitbake-devel] [PATCH v5] event: Prevent bitbake from executing event handler for wrong multiconfig target
  2021-02-10 11:15 [PATCH v5] event: Prevent bitbake from executing event handler for wrong multiconfig target Tomasz Dziendzielski
@ 2021-02-16 12:39 ` Richard Purdie
  2021-03-05 23:37 ` Richard Purdie
  1 sibling, 0 replies; 5+ messages in thread
From: Richard Purdie @ 2021-02-16 12:39 UTC (permalink / raw)
  To: Tomasz Dziendzielski, bitbake-devel

On Wed, 2021-02-10 at 12:15 +0100, Tomasz Dziendzielski wrote:
> 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.
> 
> Signed-off-by: Tomasz Dziendzielski <tomasz.dziendzielski@gmail.com>
> 
> --- v5 move the whole logic to event.bb, fix tests
> ---
>  lib/bb/cookerdata.py |  2 +-
>  lib/bb/event.py      | 26 ++++++++++++++++++++++++--
>  lib/bb/parse/ast.py  |  2 +-
>  lib/bb/runqueue.py   |  4 ++--
>  4 files changed, 28 insertions(+), 6 deletions(-)

Thanks for persevering with this one, its a great fix to get in! It
passed testing and has now merged.

Cheers,

Richard


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bitbake-devel] [PATCH v5] event: Prevent bitbake from executing event handler for wrong multiconfig target
  2021-02-10 11:15 [PATCH v5] event: Prevent bitbake from executing event handler for wrong multiconfig target Tomasz Dziendzielski
  2021-02-16 12:39 ` [bitbake-devel] " Richard Purdie
@ 2021-03-05 23:37 ` Richard Purdie
  2021-03-06 12:50   ` Tomasz Dziendzielski
  1 sibling, 1 reply; 5+ messages in thread
From: Richard Purdie @ 2021-03-05 23:37 UTC (permalink / raw)
  To: Tomasz Dziendzielski, bitbake-devel; +Cc: Peter Kjellerstedt

On Wed, 2021-02-10 at 12:15 +0100, Tomasz Dziendzielski wrote:
> 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.
> 
> Signed-off-by: Tomasz Dziendzielski <tomasz.dziendzielski@gmail.com>
> 
> --- v5 move the whole logic to event.bb, fix tests

Somehow I suspect this patch is causing a parsing speed regression:

https://autobuilder.yocto.io/pub/non-release/20210305-7/testresults/buildperf-ubuntu1604/perf-ubuntu1604_master_20210305150036_c8075ed8f1.html

See the "test3: Bitbake parsing (bitbake -p)" where you see bitbake -p
goes from 19s to 22-23s. With more layers the issue becomes more 
pronounced.

I haven't 100% confirmed this yet or looked into it but we need to find
out what cause the parsing speed regression from around this time...

Cheers,

Richard




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bitbake-devel] [PATCH v5] event: Prevent bitbake from executing event handler for wrong multiconfig target
  2021-03-05 23:37 ` Richard Purdie
@ 2021-03-06 12:50   ` Tomasz Dziendzielski
  2021-03-11 13:48     ` Richard Purdie
  0 siblings, 1 reply; 5+ messages in thread
From: Tomasz Dziendzielski @ 2021-03-06 12:50 UTC (permalink / raw)
  To: Richard Purdie; +Cc: bitbake-devel, Peter Kjellerstedt

[-- Attachment #1: Type: text/plain, Size: 1407 bytes --]

>Somehow I suspect this patch is causing a parsing speed regression:
>
>
https://autobuilder.yocto.io/pub/non-release/20210305-7/testresults/buildperf-ubuntu1604/perf-ubuntu1604_master_20210305150036_c8075ed8f1.html
>
>See the "test3: Bitbake parsing (bitbake -p)" where you see bitbake -p
>goes from 19s to 22-23s. With more layers the issue becomes more
>pronounced.
>
>I haven't 100% confirmed this yet or looked into it but we need to find
>out what cause the parsing speed regression from around this time...

It's possible this patch is causing the regression, since in
fire_class_handlers we iterate over the _BBHANDLERS_MC list multiple times
to check if it contains an event name.

def fire_class_handlers(event, d):
...
+ if d and not name in (d.getVar("__BBHANDLERS_MC") or []):
+ continue

I've sent a patch changing this structure into a set that is faster than
list in checking if an item is present in the structure. Anyway, I can't
confirm if it is the case, since the difference in parsing time is not
significant in my environment. If not, then it's still good to merge it.
https://lists.openembedded.org/g/bitbake-devel/message/12072

Please note that this patch might conflict with:
https://lists.openembedded.org/g/bitbake-devel/message/12053
so one of them will require adaptation depending on the order of merging.

Best regards,
Tomasz Dziendzielski

[-- Attachment #2: Type: text/html, Size: 2025 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bitbake-devel] [PATCH v5] event: Prevent bitbake from executing event handler for wrong multiconfig target
  2021-03-06 12:50   ` Tomasz Dziendzielski
@ 2021-03-11 13:48     ` Richard Purdie
  0 siblings, 0 replies; 5+ messages in thread
From: Richard Purdie @ 2021-03-11 13:48 UTC (permalink / raw)
  To: Tomasz Dziendzielski; +Cc: bitbake-devel, Peter Kjellerstedt

On Sat, 2021-03-06 at 13:50 +0100, Tomasz Dziendzielski wrote:
> > Somehow I suspect this patch is causing a parsing speed regression:
> > 
> > https://autobuilder.yocto.io/pub/non-release/20210305-7/testresults/buildperf-ubuntu1604/perf-ubuntu1604_master_20210305150036_c8075ed8f1.html
> > 
> > See the "test3: Bitbake parsing (bitbake -p)" where you see bitbake -p
> > goes from 19s to 22-23s. With more layers the issue becomes more
> > pronounced.
> > 
> > I haven't 100% confirmed this yet or looked into it but we need to find
> > out what cause the parsing speed regression from around this time...
> 
> It's possible this patch is causing the regression, since in fire_class_handlers we iterate over the
> _BBHANDLERS_MC list multiple times to check if it contains an event name.
> 
>  def fire_class_handlers(event, d):
> ...
> + if d and not name in (d.getVar("__BBHANDLERS_MC") or []):
> + continue
> 
> I've sent a patch changing this structure into a set that is faster than list in checking if an item is
> present in the structure. Anyway, I can't confirm if it is the case, since the difference in parsing time is
> not significant in my environment. If not, then it's still good to merge it.
> https://lists.openembedded.org/g/bitbake-devel/message/12072
> 
> Please note that this patch might conflict with:
> https://lists.openembedded.org/g/bitbake-devel/message/12053
> so one of them will require adaptation depending on the order of merging.

I firstly confirmed this was the patch causing the regression which it 
was. I then ran it under bitbake -p -P with an empty cache and you can
see a lot of time is spent in register(). Through the call traces, it was
spending the time in __len__ of the datastore. From there you can realise
that calling "if data is not None" is much more efficient than "if data".

I've sent out a patch for this and the set() fix.

Cheers,

Richard



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-03-11 13:48 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-10 11:15 [PATCH v5] event: Prevent bitbake from executing event handler for wrong multiconfig target Tomasz Dziendzielski
2021-02-16 12:39 ` [bitbake-devel] " Richard Purdie
2021-03-05 23:37 ` Richard Purdie
2021-03-06 12:50   ` Tomasz Dziendzielski
2021-03-11 13:48     ` Richard Purdie

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.