diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-02-13 21:45:51 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-02-14 20:59:02 +0100 |
commit | 58382e9572559f88ed57f5c4899a37d489bcb220 (patch) | |
tree | 84a2616485e240f2cf5261e60d79a1bf45ae2b16 /resource/image_cache.go | |
parent | 53dac9a5067dfd84283a2b2d837738a63b63b596 (diff) |
resource: Fix multi-threaded image processing issue
When doing something like this with the same image from a partial used in, say, both the home page and the single page:
```bash
{{ with $img }}
{{ $big := .Fill "1024x512 top" }}
{{ $small := $big.Resize "512x" }}
{{ end }}
```
There would be timing issues making Hugo in some cases try to process the same image with the same instructions in parallel.
You would experience errors of type:
```bash
png: invalid format: not enough pixel data
```
This commit works around that by adding a mutex per image. This should also improve the performance, sligthly, as it avoids duplicate work.
The current workaround before this fix is to always operate on the original:
```bash
{{ with $img }}
{{ $big := .Fill "1024x512 top" }}
{{ $small := .Fill "512x256 top" }}
{{ end }}
```
Fixes #4404
Diffstat (limited to 'resource/image_cache.go')
-rw-r--r-- | resource/image_cache.go | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/resource/image_cache.go b/resource/image_cache.go index 5720fb623..250155db1 100644 --- a/resource/image_cache.go +++ b/resource/image_cache.go @@ -28,7 +28,8 @@ type imageCache struct { absCacheDir string pathSpec *helpers.PathSpec mu sync.RWMutex - store map[string]*Image + + store map[string]*Image } func (c *imageCache) isInCache(key string) bool { @@ -69,6 +70,11 @@ func (c *imageCache) getOrCreate( } // Now look in the file cache. + // Multiple Go routines can invoke same operation on the same image, so + // we need to make sure this is serialized per source image. + parent.createMu.Lock() + defer parent.createMu.Unlock() + cacheFilename := filepath.Join(c.absCacheDir, key) // The definition of this counter is not that we have processed that amount |