]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Fix potential deadlock in ByParam
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 29 May 2023 10:58:22 +0000 (12:58 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 29 May 2023 12:01:07 +0000 (14:01 +0200)
Fixes #11039

langs/language.go
resources/page/pages_sort.go
resources/page/taxonomy.go
tpl/collections/sort.go

index 4e089606c7bdae136ceb038dce66717dd031652f..f8d4f64b5a67ee1e9308120e2bc232123202f122 100644 (file)
@@ -41,8 +41,11 @@ type Language struct {
        translator    locales.Translator
        timeFormatter htime.TimeFormatter
        tag           language.Tag
-       collator      *Collator
-       location      *time.Location
+       // collator1 and collator2 are the same, we have 2 to prevent deadlocks.
+       collator1 *Collator
+       collator2 *Collator
+
+       location *time.Location
 
        // This is just an alias of Site.Params.
        params maps.Params
@@ -58,14 +61,20 @@ func NewLanguage(lang, defaultContentLanguage, timeZone string, languageConfig L
                }
        }
 
-       var coll *Collator
+       var coll1, coll2 *Collator
        tag, err := language.Parse(lang)
        if err == nil {
-               coll = &Collator{
+               coll1 = &Collator{
+                       c: collate.New(tag),
+               }
+               coll2 = &Collator{
                        c: collate.New(tag),
                }
        } else {
-               coll = &Collator{
+               coll1 = &Collator{
+                       c: collate.New(language.English),
+               }
+               coll2 = &Collator{
                        c: collate.New(language.English),
                }
        }
@@ -76,7 +85,8 @@ func NewLanguage(lang, defaultContentLanguage, timeZone string, languageConfig L
                translator:     translator,
                timeFormatter:  htime.NewTimeFormatter(translator),
                tag:            tag,
-               collator:       coll,
+               collator1:      coll1,
+               collator2:      coll2,
        }
 
        return l, l.loadLocation(timeZone)
@@ -165,8 +175,12 @@ func GetLocation(l *Language) *time.Location {
        return l.location
 }
 
-func GetCollator(l *Language) *Collator {
-       return l.collator
+func GetCollator1(l *Language) *Collator {
+       return l.collator1
+}
+
+func GetCollator2(l *Language) *Collator {
+       return l.collator2
 }
 
 type Collator struct {
index b9b905cc22742df613b5480a41d9bb1b35e7e4fc..32b1b3895c2013aa75026e9c20d3b6dd29ff3a35 100644 (file)
@@ -161,7 +161,7 @@ var collatorStringSort = func(getString func(Page) string) func(p Pages) {
                // Pages may be a mix of multiple languages, so we need to use the language
                // for the currently rendered Site.
                currentSite := p[0].Site().Current()
-               coll := langs.GetCollator(currentSite.Language())
+               coll := langs.GetCollator1(currentSite.Language())
                coll.Lock()
                defer coll.Unlock()
 
@@ -173,7 +173,7 @@ var collatorStringSort = func(getString func(Page) string) func(p Pages) {
 
 var collatorStringCompare = func(getString func(Page) string, p1, p2 Page) int {
        currentSite := p1.Site().Current()
-       coll := langs.GetCollator(currentSite.Language())
+       coll := langs.GetCollator1(currentSite.Language())
        coll.Lock()
        c := coll.CompareStrings(getString(p1), getString(p2))
        coll.Unlock()
@@ -182,7 +182,9 @@ var collatorStringCompare = func(getString func(Page) string, p1, p2 Page) int {
 
 var collatorStringLess = func(p Page) (less func(s1, s2 string) bool, close func()) {
        currentSite := p.Site().Current()
-       coll := langs.GetCollator(currentSite.Language())
+       // Make sure to use the second collator to prevent deadlocks.
+       // See issue 11039.
+       coll := langs.GetCollator2(currentSite.Language())
        coll.Lock()
        return func(s1, s2 string) bool {
                        return coll.CompareStrings(s1, s2) < 1
index f50152f901a6f053a22da746b531da40fd8c86ff..3aa0c7a7b76ddec3ee325cccd842a401735ba8a7 100644 (file)
@@ -83,7 +83,7 @@ func (i Taxonomy) Alphabetical() OrderedTaxonomy {
                return ia
        }
        currentSite := p.Site().Current()
-       coll := langs.GetCollator(currentSite.Language())
+       coll := langs.GetCollator1(currentSite.Language())
        coll.Lock()
        defer coll.Unlock()
        name := func(i1, i2 *OrderedTaxonomyEntry) bool {
index 83029b3102609717badf019a045bdc88df7c71a1..4a2106039ad4167bf196f7bfd89efeafe123a5f7 100644 (file)
@@ -46,7 +46,7 @@ func (ns *Namespace) Sort(l any, args ...any) (any, error) {
                return nil, errors.New("can't sort " + reflect.ValueOf(l).Type().String())
        }
 
-       collator := langs.GetCollator(ns.deps.Conf.Language())
+       collator := langs.GetCollator1(ns.deps.Conf.Language())
 
        // Create a list of pairs that will be used to do the sort
        p := pairList{Collator: collator, sortComp: ns.sortComp, SortAsc: true, SliceType: sliceType}