Commit 10aeb672 authored by Tim Cooper's avatar Tim Cooper Committed by Brad Fitzpatrick

image: make RegisterFormat safe for concurrent use

Fixes #25884

Change-Id: I5478846ef78aecac32078ea8c3248db52f1bb534
Reviewed-on: https://go-review.googlesource.com/118755Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 94f48ddb
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"bufio" "bufio"
"errors" "errors"
"io" "io"
"sync"
"sync/atomic"
) )
// ErrFormat indicates that decoding encountered an unknown format. // ErrFormat indicates that decoding encountered an unknown format.
...@@ -21,7 +23,10 @@ type format struct { ...@@ -21,7 +23,10 @@ type format struct {
} }
// Formats is the list of registered formats. // Formats is the list of registered formats.
var formats []format var (
formatsMu sync.Mutex
atomicFormats atomic.Value
)
// RegisterFormat registers an image format for use by Decode. // RegisterFormat registers an image format for use by Decode.
// Name is the name of the format, like "jpeg" or "png". // Name is the name of the format, like "jpeg" or "png".
...@@ -30,7 +35,10 @@ var formats []format ...@@ -30,7 +35,10 @@ var formats []format
// Decode is the function that decodes the encoded image. // Decode is the function that decodes the encoded image.
// DecodeConfig is the function that decodes just its configuration. // DecodeConfig is the function that decodes just its configuration.
func RegisterFormat(name, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error)) { func RegisterFormat(name, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error)) {
formats = append(formats, format{name, magic, decode, decodeConfig}) formatsMu.Lock()
formats, _ := atomicFormats.Load().([]format)
atomicFormats.Store(append(formats, format{name, magic, decode, decodeConfig}))
formatsMu.Unlock()
} }
// A reader is an io.Reader that can also peek ahead. // A reader is an io.Reader that can also peek ahead.
...@@ -62,6 +70,7 @@ func match(magic string, b []byte) bool { ...@@ -62,6 +70,7 @@ func match(magic string, b []byte) bool {
// Sniff determines the format of r's data. // Sniff determines the format of r's data.
func sniff(r reader) format { func sniff(r reader) format {
formats, _ := atomicFormats.Load().([]format)
for _, f := range formats { for _, f := range formats {
b, err := r.Peek(len(f.magic)) b, err := r.Peek(len(f.magic))
if err == nil && match(f.magic, b) { if err == nil && match(f.magic, b) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment