diff mbox series

checklayer: fix get_depgraph() hang when command fails

Message ID 20260215221057.2776109-1-tim.orling@konsulko.com
State New
Headers show
Series checklayer: fix get_depgraph() hang when command fails | expand

Commit Message

Tim Orling Feb. 15, 2026, 10:10 p.m. UTC
From: Tim Orling <tim.orling@konsulko.com>

The get_depgraph() function hangs indefinitely when a layer causes
command failures (e.g. meta-virtualization) because:

1. bb.command.CommandFailed was not included in the event mask passed
   to set_event_mask(), so the failure event was silently dropped and
   the while True loop never received a terminating event.

2. There was no timeout handling for the case where wait_event()
   repeatedly returns None, leaving no escape from the loop.

Add CommandFailed to the event mask so failure events are properly
received and handled. Also add a timeout counter that raises
RuntimeError after 300 consecutive seconds of no events, preventing
an infinite hang.

Fixes [YOCTO #16170]

Signed-off-by: Tim Orling <tim.orling@konsulko.com>
---
 scripts/lib/checklayer/__init__.py | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/scripts/lib/checklayer/__init__.py b/scripts/lib/checklayer/__init__.py
index 86aadf39a6..b70cef1b14 100644
--- a/scripts/lib/checklayer/__init__.py
+++ b/scripts/lib/checklayer/__init__.py
@@ -360,12 +360,15 @@  def get_depgraph(targets=['world'], failsafe=False):
     depgraph = None
     with bb.tinfoil.Tinfoil() as tinfoil:
         tinfoil.prepare(config_only=False)
-        tinfoil.set_event_mask(['bb.event.NoProvider', 'bb.event.DepTreeGenerated', 'bb.command.CommandCompleted'])
+        tinfoil.set_event_mask(['bb.event.NoProvider', 'bb.event.DepTreeGenerated', 'bb.command.CommandCompleted', 'bb.command.CommandFailed'])
         if not tinfoil.run_command('generateDepTreeEvent', targets, 'do_build'):
             raise RuntimeError('starting generateDepTreeEvent failed')
+        timeouts = 0
+        max_timeouts = 300
         while True:
             event = tinfoil.wait_event(timeout=1000)
             if event:
+                timeouts = 0
                 if isinstance(event, bb.command.CommandFailed):
                     raise RuntimeError('Generating dependency information failed: %s' % event.error)
                 elif isinstance(event, bb.command.CommandCompleted):
@@ -382,6 +385,10 @@  def get_depgraph(targets=['world'], failsafe=False):
                         raise RuntimeError('Nothing provides %s.' % (event._item))
                 elif isinstance(event, bb.event.DepTreeGenerated):
                     depgraph = event._depgraph
+            else:
+                timeouts += 1
+                if timeouts > max_timeouts:
+                    raise RuntimeError('Timed out waiting for dependency graph generation to complete after %d seconds' % max_timeouts)
 
     if depgraph is None:
         raise RuntimeError('Could not retrieve the depgraph.')