Skip to content

Commit

Permalink
hugolib: Fix freeze in invalid front matter error case
Browse files Browse the repository at this point in the history
Fixes #4526
  • Loading branch information
bep committed Mar 24, 2018
1 parent e9c7b62 commit 93e24a0
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 14 deletions.
42 changes: 42 additions & 0 deletions hugolib/hugo_sites_build_failures_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package hugolib

import (
"fmt"
"testing"
)

// https://github.com/gohugoio/hugo/issues/4526
func TestSiteBuildFailureInvalidPageMetadata(t *testing.T) {
t.Parallel()

validContentFile := `
---
title = "This is good"
---
Some content.
`

invalidContentFile := `
---
title = "PDF EPUB: Anne Bradstreet: Poems "The Prologue Summary And Analysis EBook Full Text "
---
Some content.
`

var contentFiles []string
for i := 0; i <= 30; i++ {
name := fmt.Sprintf("valid%d.md", i)
contentFiles = append(contentFiles, name, validContentFile)
if i%5 == 0 {
name = fmt.Sprintf("invalid%d.md", i)
contentFiles = append(contentFiles, name, invalidContentFile)
}
}

b := newTestSitesBuilder(t)
b.WithSimpleConfigFile().WithContent(contentFiles...)
b.CreateSites().BuildFail(BuildCfg{})

}
36 changes: 31 additions & 5 deletions hugolib/page_bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type siteContentProcessor struct {

handleContent contentHandler

ctx context.Context

// The input file bundles.
fileBundlesChan chan *bundleDir

Expand All @@ -51,7 +53,28 @@ type siteContentProcessor struct {
partialBuild bool
}

func newSiteContentProcessor(baseDir string, partialBuild bool, s *Site) *siteContentProcessor {
func (s *siteContentProcessor) processBundle(b *bundleDir) {
select {
case s.fileBundlesChan <- b:
case <-s.ctx.Done():
}
}

func (s *siteContentProcessor) processSingle(fi *fileInfo) {
select {
case s.fileSinglesChan <- fi:
case <-s.ctx.Done():
}
}

func (s *siteContentProcessor) processAssets(assets []string) {
select {
case s.fileAssetsChan <- assets:
case <-s.ctx.Done():
}
}

func newSiteContentProcessor(ctx context.Context, baseDir string, partialBuild bool, s *Site) *siteContentProcessor {
numWorkers := 12
if n := runtime.NumCPU() * 3; n > numWorkers {
numWorkers = n
Expand All @@ -60,6 +83,7 @@ func newSiteContentProcessor(baseDir string, partialBuild bool, s *Site) *siteCo
numWorkers = int(math.Ceil(float64(numWorkers) / float64(len(s.owner.Sites))))

return &siteContentProcessor{
ctx: ctx,
partialBuild: partialBuild,
baseDir: baseDir,
site: s,
Expand All @@ -80,7 +104,7 @@ func (s *siteContentProcessor) closeInput() {

func (s *siteContentProcessor) process(ctx context.Context) error {
g1, ctx := errgroup.WithContext(ctx)
g2, _ := errgroup.WithContext(ctx)
g2, ctx := errgroup.WithContext(ctx)

// There can be only one of these per site.
g1.Go(func() error {
Expand Down Expand Up @@ -161,12 +185,14 @@ func (s *siteContentProcessor) process(ctx context.Context) error {
})
}

if err := g2.Wait(); err != nil {
return err
}
err := g2.Wait()

close(s.pagesChan)

if err != nil {
return err
}

if err := g1.Wait(); err != nil {
return err
}
Expand Down
19 changes: 11 additions & 8 deletions hugolib/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -1281,19 +1281,19 @@ func (c *contentCaptureResultHandler) getContentProcessor(lang string) *siteCont
func (c *contentCaptureResultHandler) handleSingles(fis ...*fileInfo) {
for _, fi := range fis {
proc := c.getContentProcessor(fi.Lang())
proc.fileSinglesChan <- fi
proc.processSingle(fi)
}
}
func (c *contentCaptureResultHandler) handleBundles(d *bundleDirs) {
for _, b := range d.bundles {
proc := c.getContentProcessor(b.fi.Lang())
proc.fileBundlesChan <- b
proc.processBundle(b)
}
}

func (c *contentCaptureResultHandler) handleCopyFiles(filenames ...string) {
for _, proc := range c.contentProcessors {
proc.fileAssetsChan <- filenames
proc.processAssets(filenames)
}
}

Expand All @@ -1309,7 +1309,7 @@ func (s *Site) readAndProcessContent(filenames ...string) error {
var defaultContentProcessor *siteContentProcessor
sites := s.owner.langSite()
for k, v := range sites {
proc := newSiteContentProcessor(baseDir, len(filenames) > 0, v)
proc := newSiteContentProcessor(ctx, baseDir, len(filenames) > 0, v)
contentProcessors[k] = proc
if k == defaultContentLanguage {
defaultContentProcessor = proc
Expand Down Expand Up @@ -1337,15 +1337,18 @@ func (s *Site) readAndProcessContent(filenames ...string) error {

c := newCapturer(s.Log, sourceSpec, handler, bundleMap, baseDir, filenames...)

if err := c.capture(); err != nil {
return err
}
err1 := c.capture()

for _, proc := range contentProcessors {
proc.closeInput()
}

return g.Wait()
err2 := g.Wait()

if err1 != nil {
return err1
}
return err2
}

func (s *Site) buildSiteMeta() (err error) {
Expand Down
12 changes: 11 additions & 1 deletion hugolib/testhelpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,22 @@ func (s *sitesBuilder) CreateSites() *sitesBuilder {
}

func (s *sitesBuilder) Build(cfg BuildCfg) *sitesBuilder {
return s.build(cfg, false)
}

func (s *sitesBuilder) BuildFail(cfg BuildCfg) *sitesBuilder {
return s.build(cfg, true)
}

func (s *sitesBuilder) build(cfg BuildCfg, shouldFail bool) *sitesBuilder {
if s.H == nil {
s.CreateSites()
}
err := s.H.Build(cfg)
if err != nil {
if err != nil && !shouldFail {
s.Fatalf("Build failed: %s", err)
} else if err == nil && shouldFail {
s.Fatalf("Expected error")
}

return s
Expand Down

0 comments on commit 93e24a0

Please sign in to comment.