From 3cf8015a4941c43ae82100dc0d998945485d760c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 25 Aug 2020 16:18:58 +0200 Subject: Fix bug in interaction of unmatch logic with target groups --- libbuild2/algorithm.cxx | 2 +- libbuild2/algorithm.ixx | 9 +++++++-- libbuild2/operation.cxx | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index 75540ff..5b340c7 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -584,7 +584,7 @@ namespace build2 else l.offset = target::offset_tried; - return r; // Group state. + return r; // Group state (must be consistent with matched_state()). } try diff --git a/libbuild2/algorithm.ixx b/libbuild2/algorithm.ixx index 9d77d61..97a8519 100644 --- a/libbuild2/algorithm.ixx +++ b/libbuild2/algorithm.ixx @@ -322,12 +322,17 @@ namespace build2 if (s == target_state::failed) throw failed (); + // If this is a member of the group then the state we've got is that of + // the group, not the member, while the member has matched the group and + // incremented its dependency counts. As a result, we cannot rely on the + // unchanged state in this case. + // switch (um) { case unmatch::none: break; case unmatch::unchanged: { - if (s == target_state::unchanged) + if (s == target_state::unchanged && t.group == nullptr) return make_pair (true, s); break; @@ -338,7 +343,7 @@ namespace build2 // we never decrement this count during match so that someone else // cannot change their mind). // - if (s == target_state::unchanged || + if ((s == target_state::unchanged && t.group == nullptr) || t[a].dependents.load (memory_order_consume) != 0) return make_pair (true, s); diff --git a/libbuild2/operation.cxx b/libbuild2/operation.cxx index a14dfb7..1594d8b 100644 --- a/libbuild2/operation.cxx +++ b/libbuild2/operation.cxx @@ -442,6 +442,21 @@ namespace build2 // haven't failed (in which case we could have bailed out early). // assert (ctx.target_count.load (memory_order_relaxed) == 0); + +#ifndef NDEBUG + if (ctx.dependency_count.load (memory_order_relaxed) != 0) + { + diag_record dr; + dr << info << "detected unexecuted matched targets:"; + + for (const auto& pt: ctx.targets) + { + const target& t (*pt); + if (size_t n = t[a].dependents.load (memory_order_relaxed)) + dr << text << t << ' ' << n; + } + } +#endif assert (ctx.dependency_count.load (memory_order_relaxed) == 0); } -- cgit v1.1