From: Philippe Coval Date: Sun, 27 Aug 2017 13:10:01 +0000 (+0200) Subject: Fix a pendning children and side effects bug X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=be26e6e43be56e814af1372f203e1b2748eebb04;p=platform%2Fupstream%2Fscons.git Fix a pendning children and side effects bug Bug: http://scons.tigris.org/issues/show_bug.cgi?id=2777O Change-Id: Iafa328a0430c675d52cdba50e6984e4c3e74e29e Credit-to: Emil Stanchev Origin: http://scons.tigris.org/nonav/issues/showattachment.cgi/894/Fix-a-pending-children-and-side-effects-bug_v3.patch --- diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 17507a6f..b77c375a 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -1016,6 +1016,27 @@ class Taskmaster(object): to_visit = to_visit | parents pending_children = pending_children - parents + # Clean up the other branches of side effect + for se in node.get_side_effects(): + waiting_s_e = se.get_waiting_s_e() + pending_children = pending_children - waiting_s_e + stack = set(waiting_s_e) + if T: + for n in waiting_s_e: + T.write(self.trace_message(' removing side effect parent %s from the pending children set\n' % + self.trace_node(n))) + while stack: + n = stack.pop() + waiting_parents = n.waiting_parents + n.waiting_parents = set() + stack = stack | waiting_parents + pending_children = pending_children - waiting_parents + + for p in waiting_parents: + p.ref_count = p.ref_count - 1 + if T: T.write(self.trace_message(' removing parent %s from the pending children set\n' % + self.trace_node(p))) + for p in parents: p.ref_count = p.ref_count - 1 if T: T.write(self.trace_message(' removing parent %s from the pending children set\n' % diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index d237d60a..430b56d0 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -34,6 +34,7 @@ import TestUnit import SCons.Taskmaster import SCons.Errors +import SCons.Job built_text = None @@ -181,8 +182,17 @@ class Node(object): wp.add(node) return 1 + def add_to_waiting_s_e(self, node): + self.waiting_s_e.add(node) + def get_state(self): return self.state + + def get_side_effects(self): + return self.side_effects + + def get_waiting_s_e(self): + return self.waiting_s_e def set_state(self, state): self.state = state @@ -235,7 +245,7 @@ class Node(object): def get_all_prerequisites(self): return [] def get_action_side_effects(self): - return [] + return [se for t in self.targets for se in t.side_effects] self.executor = Executor() self.executor.targets = self.targets return self.executor @@ -1007,6 +1017,26 @@ class TaskmasterTestCase(unittest.TestCase): t.execute() assert built_text is None, built_text assert cache_text == ["n7 retrieved", "n8 retrieved"], cache_text + + def test_pending_children_side_effects(self): + n1 = Node("n1") + n2 = Node("n2") + n3 = Node("n3") + n4 = Node("n4") + side_effect = Node("se") + + def build_error(): + import time; time.sleep(2) + raise SystemError("Node failed.") + n1.build = build_error + n1.side_effects = [side_effect] + n2.side_effects = [side_effect] + + n3.kids = [n2] + n4.kids = [n1, n2, n3] + tm = SCons.Taskmaster.Taskmaster([n4]) + jobs = SCons.Job.Jobs(2, tm) + jobs.run() def test_cached_execute(self): """Test executing a task with cached targets