From 32585696be70dba987dbad299b22a05f9a820a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Mon, 29 May 2023 12:58:22 +0200 Subject: [PATCH] Fix potential deadlock in ByParam Fixes #11039 --- langs/language.go | 30 ++++++++++++++++++++++-------- resources/page/pages_sort.go | 8 +++++--- resources/page/taxonomy.go | 2 +- tpl/collections/sort.go | 2 +- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/langs/language.go b/langs/language.go index 4e089606c7b..f8d4f64b5a6 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 b9b905cc227..32b1b3895c2 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 f50152f901a..3aa0c7a7b76 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 83029b31026..4a2106039ad 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}