diff options
| author | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-10-14 11:34:42 +0200 |
|---|---|---|
| committer | Christian Kandeler <christian.kandeler@digia.com> | 2013-10-14 17:03:17 +0200 |
| commit | c939d3bb79619229626ccd02ea7deabe5debf060 (patch) | |
| tree | cd69e3f8b699665aad9d7d2e80323f2ab08a6924 /src/lib/buildgraph | |
| parent | 3343f681c71f821aa9460f184c30e5ecf3781776 (diff) | |
| download | qbs-c939d3bb79619229626ccd02ea7deabe5debf060.tar.gz | |
detect cycles in rule dependencies
This fixes a stack overflow that occurred when having cycles in rule
dependencies.
Task-number: QBS-396
Change-Id: I1907ef66d74340c090b09be72d2352892baca986
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
Diffstat (limited to 'src/lib/buildgraph')
| -rw-r--r-- | src/lib/buildgraph/rulegraph.cpp | 24 | ||||
| -rw-r--r-- | src/lib/buildgraph/rulegraph.h | 3 |
2 files changed, 23 insertions, 4 deletions
diff --git a/src/lib/buildgraph/rulegraph.cpp b/src/lib/buildgraph/rulegraph.cpp index c2653ad7e..b33c8891d 100644 --- a/src/lib/buildgraph/rulegraph.cpp +++ b/src/lib/buildgraph/rulegraph.cpp @@ -29,6 +29,7 @@ #include "rulegraph.h" #include <language/language.h> +#include <logging/translator.h> #include <tools/error.h> namespace qbs { @@ -79,7 +80,9 @@ QList<RuleConstPtr> RuleGraph::topSorted() QList<RuleConstPtr> result; foreach (int rootIndex, rootRules) { RuleConstPtr rule = m_artifacts.at(rootIndex); - result.append(topSort(rule)); + QSet<const Rule *> seenRules; + QList<const Rule *> rulePath; + result.append(topSort(rule, &seenRules, &rulePath)); } // remove duplicates from the result of our post-order traversal @@ -182,13 +185,28 @@ void RuleGraph::removeSiblings(const Rule *rule) } } -QList<RuleConstPtr> RuleGraph::topSort(const RuleConstPtr &rule) +QList<RuleConstPtr> RuleGraph::topSort(const RuleConstPtr &rule, QSet<const Rule *> *seenRules, + QList<const Rule *> *rulePath) { + if (seenRules->contains(rule.data())) { + QString pathstr; + foreach (const Rule *r, *rulePath) { + pathstr += QLatin1Char('\n') + r->toString() + QLatin1Char('\t') + + r->script->location.toString(); + } + throw ErrorInfo(Tr::tr("Cycle detected in rule dependencies: %1").arg(pathstr)); + } + + seenRules->insert(rule.data()); + rulePath->prepend(rule.data()); + QList<RuleConstPtr> result; foreach (int childIndex, m_children.at(rule->ruleGraphId)) - result.append(topSort(m_artifacts.at(childIndex))); + result.append(topSort(m_artifacts.at(childIndex), seenRules, rulePath)); result.append(rule); + seenRules->remove(rule.data()); + rulePath->removeFirst(); return result; } diff --git a/src/lib/buildgraph/rulegraph.h b/src/lib/buildgraph/rulegraph.h index e1a511751..510a4789c 100644 --- a/src/lib/buildgraph/rulegraph.h +++ b/src/lib/buildgraph/rulegraph.h @@ -59,7 +59,8 @@ private: void remove(Rule *rule); void removeParents(const Rule *rule); void removeSiblings(const Rule *rule); - QList<RuleConstPtr> topSort(const RuleConstPtr &rule); + QList<RuleConstPtr> topSort(const RuleConstPtr &rule, QSet<const Rule *> *seenRules, + QList<const Rule *> *rulePath); private: QMap<FileTag, QList<const Rule*> > m_outputFileTagToRule; |
