From af5ed67002b7031e1735968674bacb5ee868165f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 30 Aug 2019 16:03:07 +0200 Subject: Cutoff diagnostics stack when switching to nested context --- libbuild2/algorithm.cxx | 4 ++++ libbuild2/context.hxx | 13 +++++++++-- libbuild2/module.cxx | 60 +++++++++++++++++++++++++++++-------------------- 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 ()); -- cgit v1.1