aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-08-30 16:03:07 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-08-30 16:03:07 +0200
commitaf5ed67002b7031e1735968674bacb5ee868165f (patch)
tree7cb6d0101168c58ebb2247e3ec79b33f816e8b1e
parent7c426821e7fb4919e84ec20bd2f88481db665e90 (diff)
Cutoff diagnostics stack when switching to nested context
-rw-r--r--libbuild2/algorithm.cxx4
-rw-r--r--libbuild2/context.hxx13
-rw-r--r--libbuild2/module.cxx60
3 files changed, 51 insertions, 26 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index 7a616a5..511850d 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -142,6 +142,10 @@ namespace build2
// target_lock
//
+ // Note that the stack may contain locks for targets from multiple nested
+ // contexts. This should be harmless (deadlock detection-wise) since
+ // contexts are assumed non-overlapping.
+ //
static
#ifdef __cpp_thread_local
thread_local
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index c2c191e..d2e38e7 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -102,9 +102,18 @@ namespace build2
// @@ CTX: document (backlinks, non-overlap etc). RW story.
//
// A context can be preempted to execute another context (we do this, for
- // example, to update build system modules).
+ // example, to update build system modules). When switching to such a nested
+ // context you may want to cutoff the diagnostics stack (and maybe insert
+ // your own entry), for example:
//
- // @@ Progress could clash.
+ // diag_frame::stack_guard diag_cutoff (nullptr);
+ //
+ // As well as suppress progress which would otherwise clash (maybe in the
+ // future we can do save/restore but then we would need some indication that
+ // we have switched to another task).
+ //
+ // Note also that any given thread should not participate in multiple
+ // schedulers at the same time (see scheduler::join/leave() for details).
//
class LIBBUILD2_SYMEXPORT context
{
diff --git a/libbuild2/module.cxx b/libbuild2/module.cxx
index 5cfb1ec..b5914cd 100644
--- a/libbuild2/module.cxx
+++ b/libbuild2/module.cxx
@@ -209,30 +209,42 @@ namespace build2
action_targets tgs;
action a (perform_id, update_id);
- // Note that for now we suppress progress since it would clash with
- // the progress of what we are already doing (maybe in the future we
- // can do save/restore but then we would need some sort of diagnostics
- // that we have switched to another task).
- //
- mo_perform.search ({}, /* parameters */
- rs, /* root scope */
- rs, /* base scope */
- path (), /* buildfile */
- rs.find_target_key (lr.first, loc),
- loc,
- tgs);
-
- mo_perform.match ({}, /* parameters */
- a,
- tgs,
- 1, /* diag (failures only) */
- false /* progress */);
-
- mo_perform.execute ({}, /* parameters */
- a,
- tgs,
- 1, /* diag (failures only) */
- false /* progress */);
+ {
+ // Cutoff the existing diagnostics stack and push our own entry.
+ //
+ diag_frame::stack_guard diag_cutoff (nullptr);
+
+ auto df = make_diag_frame (
+ [&loc, &mod](const diag_record& dr)
+ {
+ dr << info (loc) << "while loading build system module " << mod;
+ });
+
+ // Note that for now we suppress progress since it would clash with
+ // the progress of what we are already doing (maybe in the future we
+ // can do save/restore but then we would need some sort of
+ // diagnostics that we have switched to another task).
+ //
+ mo_perform.search ({}, /* parameters */
+ rs, /* root scope */
+ rs, /* base scope */
+ path (), /* buildfile */
+ rs.find_target_key (lr.first, loc),
+ loc,
+ tgs);
+
+ mo_perform.match ({}, /* parameters */
+ a,
+ tgs,
+ 1, /* diag (failures only) */
+ false /* progress */);
+
+ mo_perform.execute ({}, /* parameters */
+ a,
+ tgs,
+ 1, /* diag (failures only) */
+ false /* progress */);
+ }
assert (tgs.size () == 1);
const target& l (tgs[0].as_target ());