Fix server data race/nil pointer in withMaps
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 16 Jun 2020 08:42:41 +0000 (10:42 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 16 Jun 2020 09:48:10 +0000 (11:48 +0200)
Fixes #7392

hugolib/content_map_page.go
hugolib/hugo_sites.go
hugolib/hugo_sites_build.go
hugolib/site.go

index 8c7ecc3419643c79a8186c684412f523ca5ba78c..b5165b2a53c89a8af1c88999028f3fd74622611a 100644 (file)
@@ -47,7 +47,6 @@ func newPageMaps(h *HugoSites) *pageMaps {
                workers: para.New(h.numWorkers),
                pmaps:   mps,
        }
-
 }
 
 type pageMap struct {
index 3183242b7c2b6ecff5392285368f81963ed25f28..16de27b0d07484db1ee8399fa8e5a7494709dbe1 100644 (file)
@@ -78,7 +78,8 @@ type HugoSites struct {
        // As loaded from the /data dirs
        data map[string]interface{}
 
-       content *pageMaps
+       contentInit sync.Once
+       content     *pageMaps
 
        // Keeps track of bundle directories and symlinks to enable partial rebuilding.
        ContentChanges *contentChangeMap
@@ -92,6 +93,13 @@ type HugoSites struct {
        *testCounters
 }
 
+func (h *HugoSites) getContentMaps() *pageMaps {
+       h.contentInit.Do(func() {
+               h.content = newPageMaps(h)
+       })
+       return h.content
+}
+
 // Only used in tests.
 type testCounters struct {
        contentRenderCounter uint64
@@ -253,7 +261,7 @@ func (h *HugoSites) PrintProcessingStats(w io.Writer) {
 func (h *HugoSites) GetContentPage(filename string) page.Page {
        var p page.Page
 
-       h.content.walkBundles(func(b *contentNode) bool {
+       h.getContentMaps().walkBundles(func(b *contentNode) bool {
                if b.p == nil || b.fi == nil {
                        return false
                }
@@ -706,7 +714,7 @@ func (h *HugoSites) renderCrossSitesArtifacts() error {
 }
 
 func (h *HugoSites) removePageByFilename(filename string) {
-       h.content.withMaps(func(m *pageMap) error {
+       h.getContentMaps().withMaps(func(m *pageMap) error {
                m.deleteBundleMatching(func(b *contentNode) bool {
                        if b.p == nil {
                                return false
@@ -897,7 +905,7 @@ func (h *HugoSites) findPagesByKindIn(kind string, inPages page.Pages) page.Page
 }
 
 func (h *HugoSites) resetPageState() {
-       h.content.walkBundles(func(n *contentNode) bool {
+       h.getContentMaps().walkBundles(func(n *contentNode) bool {
                if n.p == nil {
                        return false
                }
@@ -914,7 +922,7 @@ func (h *HugoSites) resetPageState() {
 }
 
 func (h *HugoSites) resetPageStateFromEvents(idset identity.Identities) {
-       h.content.walkBundles(func(n *contentNode) bool {
+       h.getContentMaps().walkBundles(func(n *contentNode) bool {
                if n.p == nil {
                        return false
                }
index fac20e8833fb0ce59711abcd7456e2138109db5f..f39e7a7e53f540766ca37f4250c15cebec3c6bc0 100644 (file)
@@ -263,7 +263,7 @@ func (h *HugoSites) assemble(bcfg *BuildCfg) error {
                return nil
        }
 
-       if err := h.content.AssemblePages(); err != nil {
+       if err := h.getContentMaps().AssemblePages(); err != nil {
                return err
        }
 
index d544cb095718de3576207510e097e8a0f61e0844..a0390780aa92302fde1dcffca83fc53c63c3f353 100644 (file)
@@ -1296,14 +1296,12 @@ func (s *Site) readAndProcessContent(filenames ...string) error {
 
        proc := newPagesProcessor(s.h, sourceSpec)
 
-       c := newPagesCollector(sourceSpec, s.h.content, s.Log, s.h.ContentChanges, proc, filenames...)
+       c := newPagesCollector(sourceSpec, s.h.getContentMaps(), s.Log, s.h.ContentChanges, proc, filenames...)
 
        if err := c.Collect(); err != nil {
                return err
        }
 
-       s.h.content = newPageMaps(s.h)
-
        return nil
 }