aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2023-05-29 12:58:22 +0200
committerBjørn Erik Pedersen <[email protected]>2023-05-29 14:01:07 +0200
commit32585696be70dba987dbad299b22a05f9a820a49 (patch)
tree202537f9e982084a2f22c8452c7fd39374f9c8a5
parentd47225ce9ef1a1ae31d89e8aed07a6fcc9d524f2 (diff)
downloadhugo-32585696be70dba987dbad299b22a05f9a820a49.tar.gz
hugo-32585696be70dba987dbad299b22a05f9a820a49.zip
Fix potential deadlock in ByParam
Fixes #11039
-rw-r--r--langs/language.go30
-rw-r--r--resources/page/pages_sort.go8
-rw-r--r--resources/page/taxonomy.go2
-rw-r--r--tpl/collections/sort.go2
4 files changed, 29 insertions, 13 deletions
diff --git a/langs/language.go b/langs/language.go
index 4e089606c..f8d4f64b5 100644
--- a/langs/language.go
+++ b/langs/language.go
@@ -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 {
diff --git a/resources/page/pages_sort.go b/resources/page/pages_sort.go
index b9b905cc2..32b1b3895 100644
--- a/resources/page/pages_sort.go
+++ b/resources/page/pages_sort.go
@@ -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
diff --git a/resources/page/taxonomy.go b/resources/page/taxonomy.go
index f50152f90..3aa0c7a7b 100644
--- a/resources/page/taxonomy.go
+++ b/resources/page/taxonomy.go
@@ -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 {
diff --git a/tpl/collections/sort.go b/tpl/collections/sort.go
index 83029b310..4a2106039 100644
--- a/tpl/collections/sort.go
+++ b/tpl/collections/sort.go
@@ -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}