diff options
author | Fredrik Medley <fredrik.medley@gmail.com> | 2015-07-12 06:53:19 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-04-06 15:21:09 (GMT) |
commit | 7d21426c56306917ebaf16671a75215672d79755 (patch) | |
tree | 58ec26665664377828f9a56e7ed0ff387776bfbe /src/build.cc | |
parent | 78f548880e549c701bd77760e4b3f3a4ee147641 (diff) | |
download | Ninja-7d21426c56306917ebaf16671a75215672d79755.zip Ninja-7d21426c56306917ebaf16671a75215672d79755.tar.gz Ninja-7d21426c56306917ebaf16671a75215672d79755.tar.bz2 |
Release the pool slot held by an edge whether it succeeds or fails
When an edge finishes building, it should be release from its pool.
Make sure that this also is the case when an edge fails to build.
The bug can be shown with a pool has size N, then `ninja -k N+1` will
still stop after N failing commands for that pool, even if there are
many more jobs to be done for that pool:
pool mypool
depth = 1
rule bad_rule
command = false
pool = mypool
build a : bad_rule
build b : bad_rule
Current behaviour:
$ ninja -k 0
[1/2] false
FAILED: false
ninja: build stopped: cannot make progress due to previous errors.
Expected behaviour:
$ ninja -k 0
[1/2] false
FAILED: false
[2/2] false
FAILED: false
ninja: build stopped: cannot make progress due to previous errors.
Signed-off-by: Fredrik Medley <fredrik.medley@gmail.com>
Diffstat (limited to 'src/build.cc')
-rw-r--r-- | src/build.cc | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/src/build.cc b/src/build.cc index 2df5c1a..dae1e18 100644 --- a/src/build.cc +++ b/src/build.cc @@ -382,20 +382,25 @@ void Plan::ScheduleWork(Edge* edge) { } } -void Plan::EdgeFinished(Edge* edge) { +void Plan::EdgeFinished(Edge* edge, bool success) { map<Edge*, bool>::iterator e = want_.find(edge); assert(e != want_.end()); bool directly_wanted = e->second; - if (directly_wanted) - --wanted_edges_; - want_.erase(e); - edge->outputs_ready_ = true; // See if this job frees up any delayed jobs. if (directly_wanted) edge->pool()->EdgeFinished(*edge); edge->pool()->RetrieveReadyEdges(&ready_); + // The rest of this function only applies to successful commands. + if (!success) + return; + + if (directly_wanted) + --wanted_edges_; + want_.erase(e); + edge->outputs_ready_ = true; + // Check off any nodes we were waiting for with this edge. for (vector<Node*>::iterator o = edge->outputs_.begin(); o != edge->outputs_.end(); ++o) { @@ -418,7 +423,7 @@ void Plan::NodeFinished(Node* node) { } else { // We do not need to build this edge, but we might need to build one of // its dependents. - EdgeFinished(*oe); + EdgeFinished(*oe, true); } } } @@ -651,7 +656,7 @@ bool Builder::Build(string* err) { } if (edge->is_phony()) { - plan_.EdgeFinished(edge); + plan_.EdgeFinished(edge, true); } else { ++pending_commands; } @@ -770,8 +775,10 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) { &start_time, &end_time); // The rest of this function only applies to successful commands. - if (!result->success()) + if (!result->success()) { + plan_.EdgeFinished(edge, false); return true; + } // Restat the edge outputs, if necessary. TimeStamp restat_mtime = 0; @@ -820,7 +827,7 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) { } } - plan_.EdgeFinished(edge); + plan_.EdgeFinished(edge, true); // Delete any left over response file. string rspfile = edge->GetUnescapedRspfile(); |