From 11e3b0d0006609e3835f4aa04f7cd7f6039239e8 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 4 Feb 2015 10:41:00 -0800 Subject: [PATCH 1/3] Fix deadlock when there are no modules Change-Id: Ibfc1190f2b5ac3c3445d40f1b5dd0cd782e63dfd --- context.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/context.go b/context.go index 9fea1db..da4643a 100644 --- a/context.go +++ b/context.go @@ -977,8 +977,7 @@ func (c *Context) parallelVisitAllBottomUp(visit func(group *moduleGroup)) { } } -loop: - for { + for count > 0 { select { case doneGroup := <-doneCh: for _, parent := range doneGroup.reverseDeps { @@ -988,9 +987,6 @@ loop: } } count-- - if count == 0 { - break loop - } } } } From 93ef72d2836ae001cca3b923ec68b9e691af9908 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 24 Feb 2015 17:13:12 -0800 Subject: [PATCH 2/3] Don't fail cleanup when a file has turned into a directory If .ninja_log contains an entry that used to be a file but is now a non-empty directory the os.Remove call will fail. Silently ignore this error, if the files in the directory are abandoned the directory will be cleaned up when the files are removed. --- bootstrap/cleanup.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bootstrap/cleanup.go b/bootstrap/cleanup.go index 7029111..f7b1cf9 100644 --- a/bootstrap/cleanup.go +++ b/bootstrap/cleanup.go @@ -124,6 +124,11 @@ func removeFileAndEmptyDirs(path string) error { if os.IsNotExist(err) { return nil } + pathErr := err.(*os.PathError) + switch pathErr.Err { + case syscall.ENOTEMPTY, syscall.EEXIST: + return nil + } return err } From 8900e9bd37efe52cc58fb464d148801ac775592c Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 2 Mar 2015 14:03:01 -0800 Subject: [PATCH 3/3] Exit early from generateModuleBuildActions on error generateModuleBuildActions was continuing to call GenerateBuildActions on all modules even after one returned an error. This could cause a later module to panic because it was missing information that was supposed to be generated by the module that returned an error, hiding the earlier error message. If a module returns an error, stop triggering any new goroutines to call GenerateBuildActions on later modules. --- context.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/context.go b/context.go index da4643a..d64d7d2 100644 --- a/context.go +++ b/context.go @@ -955,9 +955,10 @@ func (c *Context) addDependency(module *moduleInfo, depName string) []error { return nil } -func (c *Context) parallelVisitAllBottomUp(visit func(group *moduleGroup)) { +func (c *Context) parallelVisitAllBottomUp(visit func(group *moduleGroup) bool) { doneCh := make(chan *moduleGroup) count := 0 + cancel := false for _, group := range c.moduleGroupsSorted { group.waitingCount = group.depsCount @@ -966,7 +967,10 @@ func (c *Context) parallelVisitAllBottomUp(visit func(group *moduleGroup)) { visitOne := func(group *moduleGroup) { count++ go func() { - visit(group) + ret := visit(group) + if ret { + cancel = true + } doneCh <- group }() } @@ -980,10 +984,12 @@ func (c *Context) parallelVisitAllBottomUp(visit func(group *moduleGroup)) { for count > 0 { select { case doneGroup := <-doneCh: - for _, parent := range doneGroup.reverseDeps { - parent.waitingCount-- - if parent.waitingCount == 0 { - visitOne(parent) + if !cancel { + for _, parent := range doneGroup.reverseDeps { + parent.waitingCount-- + if parent.waitingCount == 0 { + visitOne(parent) + } } } count-- @@ -1286,7 +1292,7 @@ func (c *Context) generateModuleBuildActions(config interface{}, } }() - c.parallelVisitAllBottomUp(func(group *moduleGroup) { + c.parallelVisitAllBottomUp(func(group *moduleGroup) bool { // The parent scope of the moduleContext's local scope gets overridden to be that of the // calling Go package on a per-call basis. Since the initial parent scope doesn't matter we // just set it to nil. @@ -1307,7 +1313,7 @@ func (c *Context) generateModuleBuildActions(config interface{}, if len(mctx.errs) > 0 { errsCh <- mctx.errs - break + return true } depsCh <- mctx.ninjaFileDeps @@ -1316,9 +1322,10 @@ func (c *Context) generateModuleBuildActions(config interface{}, &mctx.actionDefs, liveGlobals) if len(newErrs) > 0 { errsCh <- newErrs - break + return true } } + return false }) cancelCh <- struct{}{}