aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/adhoc-rule-regex-pattern.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-05-26 07:22:40 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-05-29 10:21:12 +0200
commitab91d32c1b23ea92b988d5618db2938a8c5dc63f (patch)
treefc02b89ae71aa3bcad127149718a7a4e7480f0b7 /libbuild2/adhoc-rule-regex-pattern.cxx
parent56d79a62e64180f639dad02f0887fef5d57bb096 (diff)
Avoid group linkup deadlocks for dynamic and pattern-static members
Diffstat (limited to 'libbuild2/adhoc-rule-regex-pattern.cxx')
-rw-r--r--libbuild2/adhoc-rule-regex-pattern.cxx36
1 files changed, 23 insertions, 13 deletions
diff --git a/libbuild2/adhoc-rule-regex-pattern.cxx b/libbuild2/adhoc-rule-regex-pattern.cxx
index 0f2ecc3..c4b4cab 100644
--- a/libbuild2/adhoc-rule-regex-pattern.cxx
+++ b/libbuild2/adhoc-rule-regex-pattern.cxx
@@ -400,21 +400,31 @@ namespace build2
if (find (ms.begin (), ms.end (), &t) != ms.end ())
continue;
- // We can only update the group under lock.
+ // Check if we already belong to this group. Note that this not a
+ // mere optimization since we may be in the member->group->member
+ // chain and trying to lock the member the second time would
+ // deadlock (this can be triggered, for example, by dist, which sort
+ // of depends on such members directly @@ maybe this should be fixed
+ // there?).
//
- target_lock tl (lock (a, t));
-
- if (!tl)
- fail << "group " << *g << " member " << t << " is already matched" <<
- info << "static group members specified by pattern rules cannot "
- << "be used as prerequisites directly, only via group";
-
- if (t.group == nullptr)
- tl.target->group = g;
- else if (t.group != g)
+ if (t.group != g) // Note: atomic.
{
- fail << "group " << *g << " member " << t
- << " is already member of group " << *t.group;
+ // We can only update the group under lock.
+ //
+ target_lock tl (lock (a, t));
+
+ if (!tl)
+ fail << "group " << *g << " member " << t << " is already matched" <<
+ info << "static group members specified by pattern rules cannot "
+ << "be used as prerequisites directly, only via group";
+
+ if (t.group == nullptr)
+ tl.target->group = g;
+ else if (t.group != g)
+ {
+ fail << "group " << *g << " member " << t
+ << " is already member of group " << *t.group;
+ }
}
}