Avoid race condition in target list init
authorbep <bjorn.erik.pedersen@gmail.com>
Fri, 20 Feb 2015 17:38:35 +0000 (18:38 +0100)
committerbep <bjorn.erik.pedersen@gmail.com>
Fri, 20 Feb 2015 17:38:35 +0000 (18:38 +0100)
As reported by Go's race detector.

See #917

hugolib/site.go

index bf9d6812e1a6969de2b79d2078e1e89102ef8cba..0acc287d5251fadf6ccef53e668c835080cfbc1e 100644 (file)
@@ -66,23 +66,24 @@ var DefaultTimer *nitro.B
 //
 // 5. The entire collection of files is written to disk.
 type Site struct {
-       Pages       Pages
-       Files       []*source.File
-       Tmpl        tpl.Template
-       Taxonomies  TaxonomyList
-       Source      source.Input
-       Sections    Taxonomy
-       Info        SiteInfo
-       Shortcodes  map[string]ShortcodeFunc
-       Menus       Menus
-       timer       *nitro.B
-       Targets     targetList
-       Completed   chan bool
-       RunMode     runmode
-       params      map[string]interface{}
-       draftCount  int
-       futureCount int
-       Data        map[string]interface{}
+       Pages          Pages
+       Files          []*source.File
+       Tmpl           tpl.Template
+       Taxonomies     TaxonomyList
+       Source         source.Input
+       Sections       Taxonomy
+       Info           SiteInfo
+       Shortcodes     map[string]ShortcodeFunc
+       Menus          Menus
+       timer          *nitro.B
+       Targets        targetList
+       targetListInit sync.Once
+       Completed      chan bool
+       RunMode        runmode
+       params         map[string]interface{}
+       draftCount     int
+       futureCount    int
+       Data           map[string]interface{}
 }
 
 type targetList struct {
@@ -1454,34 +1455,41 @@ func (s *Site) NewXMLBuffer() *bytes.Buffer {
 }
 
 func (s *Site) PageTarget() target.Output {
-       if s.Targets.Page == nil {
-               s.Targets.Page = &target.PagePub{
-                       PublishDir: s.absPublishDir(),
-                       UglyUrls:   viper.GetBool("UglyUrls"),
-               }
-       }
+       s.initTargetList()
        return s.Targets.Page
 }
 
 func (s *Site) FileTarget() target.Output {
-       if s.Targets.File == nil {
-               s.Targets.File = &target.Filesystem{
-                       PublishDir: s.absPublishDir(),
-               }
-       }
+       s.initTargetList()
        return s.Targets.File
 }
 
 func (s *Site) AliasTarget() target.AliasPublisher {
-       if s.Targets.Alias == nil {
-               s.Targets.Alias = &target.HTMLRedirectAlias{
-                       PublishDir: s.absPublishDir(),
-               }
-
-       }
+       s.initTargetList()
        return s.Targets.Alias
 }
 
+func (s *Site) initTargetList() {
+       s.targetListInit.Do(func() {
+               if s.Targets.Page == nil {
+                       s.Targets.Page = &target.PagePub{
+                               PublishDir: s.absPublishDir(),
+                               UglyUrls:   viper.GetBool("UglyUrls"),
+                       }
+               }
+               if s.Targets.File == nil {
+                       s.Targets.File = &target.Filesystem{
+                               PublishDir: s.absPublishDir(),
+                       }
+               }
+               if s.Targets.Alias == nil {
+                       s.Targets.Alias = &target.HTMLRedirectAlias{
+                               PublishDir: s.absPublishDir(),
+                       }
+               }
+       })
+}
+
 func (s *Site) WriteDestFile(path string, reader io.Reader) (err error) {
        jww.DEBUG.Println("creating file:", path)
        return s.FileTarget().Publish(path, reader)