From 95ab453345e5f6eb290133a3de7c2ca3a3666dc4 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Sun, 7 Dec 2008 04:15:22 +0000 Subject: Issue 2265: Suppress messages about spurious dependency cycles. (Jason Kenny) --- src/CHANGES.txt | 5 ++++ src/engine/SCons/Script/Interactive.py | 14 ++++----- src/engine/SCons/Taskmaster.py | 54 ++++++++++++++++++++++------------ src/engine/SCons/TaskmasterTests.py | 4 +-- test/Interactive/taskmastertrace.py | 4 +-- test/option/taskmastertrace.py | 32 ++++++++++---------- 6 files changed, 66 insertions(+), 47 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 0afce48..d415509 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -34,6 +34,11 @@ RELEASE 1.X - XXX - Handle Java inner classes declared within a method. + From Jason Kenny: + + - Suppress mistaken reports of a dependency cycle when a child + left on the pending list is a single Node in EXECUTED state. + From Steven Knight: - Fix label placement by the "scons-time.py func" subcommand diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py index 4158f99..98a312b 100644 --- a/src/engine/SCons/Script/Interactive.py +++ b/src/engine/SCons/Script/Interactive.py @@ -258,14 +258,12 @@ class SConsInteractiveCmd(cmd.Cmd): # node.set_state() to reset it manually node.set_state(SCons.Node.no_state) node.implicit = None - # Make sure Taskmaster reference counts are reset to zero. - # - # TODO: Look for a way to avoid having to reset this here - # by making sure the Taskmaster will always end up reverting - # every Node's ref_count to 0 before terminating. That may - # provide clues about intermittent phantom cycles that have - # been reported (e.g. issue 2265 at tigris.org). - node.ref_count = 0 + + # Debug: Uncomment to verify that all Taskmaster reference + # counts have been reset to zero. + #if node.ref_count != 0: + # from SCons.Debug import Trace + # Trace('node %s, ref_count %s !!!\n' % (node, node.ref_count)) SCons.SConsign.Reset() SCons.Script.Main.progress_display("scons: done clearing node information.") diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 766d894..eefe56b 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -441,7 +441,7 @@ class Task: p.ref_count = p.ref_count - subtract if T: T.write(self.trace_message('Task.postprocess()', p, - 'adjusting parent ref count')) + 'adjusted parent ref count')) if p.ref_count == 0: self.tm.candidates.append(p) @@ -820,7 +820,7 @@ class Taskmaster: # count so we can be put back on the list for # re-evaluation when they've all finished. node.ref_count = node.ref_count + child.add_to_waiting_parents(node) - if T: T.write(self.trace_message(' adjusting ref count: %s, child %s' % + if T: T.write(self.trace_message(' adjusted ref count: %s, child %s' % (self.trace_node(node), repr(str(child))))) if T: @@ -908,7 +908,7 @@ class Taskmaster: if T: for n in nodes: - T.write(self.trace_message(' removing %s from the pending children set\n' % + T.write(self.trace_message(' removing node %s from the pending children set\n' % self.trace_node(n))) try: while 1: @@ -932,10 +932,10 @@ class Taskmaster: to_visit = to_visit | parents pending_children = pending_children - parents - if T: - for p in parents: - T.write(self.trace_message(' removing %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' % + self.trace_node(p))) except KeyError: # The container to_visit has been emptied. pass @@ -955,15 +955,31 @@ class Taskmaster: """ Check for dependency cycles. """ - if self.pending_children: - desc = 'Found dependency cycle(s):\n' - for node in self.pending_children: - cycle = find_cycle([node], set()) - if cycle: - desc = desc + " " + string.join(map(str, cycle), " -> ") + "\n" - else: - desc = desc + \ - " Internal Error: no cycle found for node %s (%s) in state %s\n" % \ - (node, repr(node), StateString[node.get_state()]) - - raise SCons.Errors.UserError, desc + if not self.pending_children: + return + + # TODO(1.5) + #nclist = [ (n, find_cycle([n], set())) for n in self.pending_children ] + nclist = map(lambda n: (n, find_cycle([n], set())), self.pending_children) + + # TODO(1.5) + #genuine_cycles = [ + # node for node, cycle in nclist + # if cycle or node.get_state() != NODE_EXECUTED + #] + genuine_cycles = filter(lambda t: t[1] or t[0].get_state() != NODE_EXECUTED, nclist) + if not genuine_cycles: + # All of the "cycles" found were single nodes in EXECUTED state, + # which is to say, they really weren't cycles. Just return. + return + + desc = 'Found dependency cycle(s):\n' + for node, cycle in nclist: + if cycle: + desc = desc + " " + string.join(map(str, cycle), " -> ") + "\n" + else: + desc = desc + \ + " Internal Error: no cycle found for node %s (%s) in state %s\n" % \ + (node, repr(node), StateString[node.get_state()]) + + raise SCons.Errors.UserError, desc diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index 2031d23..b36e4aa 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -1067,7 +1067,7 @@ Taskmaster: already handled (executed) Taskmaster: Considering node and its children: Taskmaster: Taskmaster: -Taskmaster: adjusting ref count: , child 'n2' +Taskmaster: adjusted ref count: , child 'n2' Taskmaster: Considering node and its children: Taskmaster: Evaluating @@ -1076,7 +1076,7 @@ Task.prepare(): node Task.execute(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: diff --git a/test/Interactive/taskmastertrace.py b/test/Interactive/taskmastertrace.py index b274c65..4ccf46b 100644 --- a/test/Interactive/taskmastertrace.py +++ b/test/Interactive/taskmastertrace.py @@ -75,7 +75,7 @@ scons>>> Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: Taskmaster: -Taskmaster: adjusting ref count: , child 'foo.in' +Taskmaster: adjusted ref count: , child 'foo.in' Taskmaster: Considering node and its children: Taskmaster: Evaluating @@ -84,7 +84,7 @@ Task.prepare(): node Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: diff --git a/test/option/taskmastertrace.py b/test/option/taskmastertrace.py index cd6e09d..23545c1 100644 --- a/test/option/taskmastertrace.py +++ b/test/option/taskmastertrace.py @@ -53,10 +53,10 @@ Taskmaster: Taskmaster: Taskmaster: Taskmaster: -Taskmaster: adjusting ref count: , child 'SConstruct' -Taskmaster: adjusting ref count: , child 'Tfile.in' -Taskmaster: adjusting ref count: , child 'Tfile.mid' -Taskmaster: adjusting ref count: , child 'Tfile.out' +Taskmaster: adjusted ref count: , child 'SConstruct' +Taskmaster: adjusted ref count: , child 'Tfile.in' +Taskmaster: adjusted ref count: , child 'Tfile.mid' +Taskmaster: adjusted ref count: , child 'Tfile.out' Taskmaster: Considering node and its children: Taskmaster: Evaluating @@ -65,7 +65,7 @@ Task.prepare(): node Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: @@ -76,7 +76,7 @@ Task.prepare(): node Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: @@ -90,7 +90,7 @@ Copy("Tfile.mid", "Tfile.in") Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: @@ -104,7 +104,7 @@ Copy("Tfile.out", "Tfile.mid") Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: @@ -148,10 +148,10 @@ Taskmaster: Taskmaster: Taskmaster: Taskmaster: -Taskmaster: adjusting ref count: , child 'SConstruct' -Taskmaster: adjusting ref count: , child 'Tfile.in' -Taskmaster: adjusting ref count: , child 'Tfile.mid' -Taskmaster: adjusting ref count: , child 'Tfile.out' +Taskmaster: adjusted ref count: , child 'SConstruct' +Taskmaster: adjusted ref count: , child 'Tfile.in' +Taskmaster: adjusted ref count: , child 'Tfile.mid' +Taskmaster: adjusted ref count: , child 'Tfile.out' Taskmaster: Considering node and its children: Taskmaster: Evaluating @@ -160,7 +160,7 @@ Task.prepare(): node Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: @@ -171,7 +171,7 @@ Task.prepare(): node Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: @@ -184,7 +184,7 @@ Task.execute(): node Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: @@ -197,7 +197,7 @@ Task.execute(): node Task.executed_with_callbacks(): node Task.postprocess(): node Task.postprocess(): removing -Task.postprocess(): adjusting parent ref count +Task.postprocess(): adjusted parent ref count Taskmaster: Looking for a node to evaluate Taskmaster: Considering node and its children: -- cgit v0.12