diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2023-11-03 08:05:46 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2023-11-03 08:05:46 +0200 |
commit | 066980729c57e00abc3765053cf3f39e3d223a54 (patch) | |
tree | 0497ed9b08837dfc1f301851b5f2e2dcf248caad /libbuild2/algorithm.cxx | |
parent | 1c6096e53a906d7821a401d91b32ca02df3d715f (diff) |
Fix data race in match options logic
Diffstat (limited to 'libbuild2/algorithm.cxx')
-rw-r--r-- | libbuild2/algorithm.cxx | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index 1f2d88b..0e995d5 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -291,7 +291,12 @@ namespace build2 // We don't lock already applied or executed targets unless there // are new options. // - if (e >= appl && (cs.match_extra.cur_options & options) == options) + // Note: we don't have the lock yet so we must use atomic cur_options. + // We also have to re-check this once we've grabbed the lock. + // + if (e >= appl && + (cs.match_extra.cur_options_.load (memory_order_relaxed) & options) + == options) return target_lock {a, nullptr, e - b, false}; } @@ -312,7 +317,21 @@ namespace build2 offset = target::offset_touched; } else + { + // Re-check the options if already applied or worse. + // + if (e >= appl && (s.match_extra.cur_options & options) == options) + { + // Essentially unlock_impl(). + // + task_count.store (e, memory_order_release); + ctx.sched->resume (task_count); + + return target_lock {a, nullptr, e - b, false}; + } + offset = e - b; + } return target_lock {a, &t, offset, first}; } @@ -962,6 +981,7 @@ namespace build2 recipe re (ar != nullptr ? f (*ar, a, t, me) : ru.apply (a, t, me)); me.free (); // Note: cur_options are still in use. + me.cur_options_.store (me.cur_options, memory_order_relaxed); return re; } @@ -1024,6 +1044,7 @@ namespace build2 // Note: for now no adhoc_reapply(). // ru.reapply (a, t, me); + me.cur_options_.store (me.cur_options, memory_order_relaxed); } // If anything goes wrong, set target state to failed and return nullopt. |