mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-28 22:21:46 -05:00
tpl/partials: Fix partialCached deadlock regression
This is a rollback of 0927cf739f
We cannot do that change until we either completes #9570 or possibly also use the new TryLock in GO 1.18.
Fixes #9588
Opens #4086
This commit is contained in:
parent
376704d382
commit
9b8b6d34e2
2 changed files with 58 additions and 20 deletions
|
@ -103,6 +103,44 @@ P2
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #588
|
||||||
|
func TestIncludeCachedRecursionShortcode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
files := `
|
||||||
|
-- config.toml --
|
||||||
|
baseURL = 'http://example.com/'
|
||||||
|
-- content/_index.md --
|
||||||
|
---
|
||||||
|
title: "Index"
|
||||||
|
---
|
||||||
|
{{< short >}}
|
||||||
|
-- layouts/index.html --
|
||||||
|
{{ partials.IncludeCached "p1.html" . }}
|
||||||
|
-- layouts/partials/p1.html --
|
||||||
|
{{ .Content }}
|
||||||
|
{{ partials.IncludeCached "p2.html" . }}
|
||||||
|
-- layouts/partials/p2.html --
|
||||||
|
-- layouts/shortcodes/short.html --
|
||||||
|
SHORT
|
||||||
|
{{ partials.IncludeCached "p2.html" . }}
|
||||||
|
P2
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
b := hugolib.NewIntegrationTestBuilder(
|
||||||
|
hugolib.IntegrationTestConfig{
|
||||||
|
T: t,
|
||||||
|
TxtarString: files,
|
||||||
|
},
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
b.AssertFileContent("public/index.html", `
|
||||||
|
SHORT
|
||||||
|
P2
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIncludeCacheHints(t *testing.T) {
|
func TestIncludeCacheHints(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
@ -233,21 +233,14 @@ func (ns *Namespace) getOrCreate(ctx context.Context, key partialCacheKey, conte
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// We may already have a write lock.
|
ns.cachedPartials.RLock()
|
||||||
hasLock := tpl.GetHasLockFromContext(ctx)
|
|
||||||
|
|
||||||
if !hasLock {
|
|
||||||
ns.cachedPartials.RLock()
|
|
||||||
}
|
|
||||||
p, ok := ns.cachedPartials.p[key]
|
p, ok := ns.cachedPartials.p[key]
|
||||||
if !hasLock {
|
ns.cachedPartials.RUnlock()
|
||||||
ns.cachedPartials.RUnlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
if ns.deps.Metrics != nil {
|
if ns.deps.Metrics != nil {
|
||||||
ns.deps.Metrics.TrackValue(key.templateName(), p, true)
|
ns.deps.Metrics.TrackValue(key.templateName(), p, true)
|
||||||
// The templates that gets executed is measued in Execute.
|
// The templates that gets executed is measured in Execute.
|
||||||
// We need to track the time spent in the cache to
|
// We need to track the time spent in the cache to
|
||||||
// get the totals correct.
|
// get the totals correct.
|
||||||
ns.deps.Metrics.MeasureSince(key.templateName(), start)
|
ns.deps.Metrics.MeasureSince(key.templateName(), start)
|
||||||
|
@ -256,21 +249,28 @@ func (ns *Namespace) getOrCreate(ctx context.Context, key partialCacheKey, conte
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasLock {
|
// This needs to be done outside the lock.
|
||||||
ns.cachedPartials.Lock()
|
// See #9588
|
||||||
defer ns.cachedPartials.Unlock()
|
_, p, err = ns.include(ctx, key.name, context)
|
||||||
ctx = tpl.SetHasLockInContext(ctx, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
var name string
|
|
||||||
name, p, err = ns.include(ctx, key.name, context)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ns.deps.Metrics != nil {
|
ns.cachedPartials.Lock()
|
||||||
ns.deps.Metrics.TrackValue(name, p, false)
|
defer ns.cachedPartials.Unlock()
|
||||||
|
// Double-check.
|
||||||
|
if p2, ok := ns.cachedPartials.p[key]; ok {
|
||||||
|
if ns.deps.Metrics != nil {
|
||||||
|
ns.deps.Metrics.TrackValue(key.templateName(), p, true)
|
||||||
|
ns.deps.Metrics.MeasureSince(key.templateName(), start)
|
||||||
|
}
|
||||||
|
return p2, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if ns.deps.Metrics != nil {
|
||||||
|
ns.deps.Metrics.TrackValue(key.templateName(), p, false)
|
||||||
|
}
|
||||||
|
|
||||||
ns.cachedPartials.p[key] = p
|
ns.cachedPartials.p[key] = p
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
|
|
Loading…
Reference in a new issue