From c5f284a1f9c81ba1b70ea60c2db6234e70e40b4f Mon Sep 17 00:00:00 2001 From: Srevin Saju Date: Mon, 23 Oct 2023 14:10:34 +0300 Subject: [PATCH] fix(getter): race condition when SetClient is called this is a non-breaking change. this fixes an issue when Clients are created and called concurrently. clients called SetClient on each of the Getters. When no getters were provided, it modified the clients of the default getters defined in a map. Since the map was mutated from multiple goroutines, it creates a race condition 'concurrent map writes'. The issue is mitigated by creating a new copy of Getters for every new client created. SetClient now modifies its own copy of the Getter, not the default Getters --- client_option.go | 2 +- get.go | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/client_option.go b/client_option.go index b16413753..b1763f0f5 100644 --- a/client_option.go +++ b/client_option.go @@ -37,7 +37,7 @@ func (c *Client) Configure(opts ...ClientOption) error { c.Detectors = Detectors } if c.Getters == nil { - c.Getters = Getters + c.Getters = DefaultGetters() } // Set the client for each getter, so the top-level client can know diff --git a/get.go b/get.go index c233763c6..e7fb87840 100644 --- a/get.go +++ b/get.go @@ -59,12 +59,14 @@ var forcedRegexp = regexp.MustCompile(`^([A-Za-z0-9]+)::(.+)$`) // httpClient is the default client to be used by HttpGetters. var httpClient = cleanhttp.DefaultClient() -func init() { +// DefaultGetters returns the default set of getters. This is used by the +// Client if no Getters are specified. It returns a new independent map. +func DefaultGetters() map[string]Getter { httpGetter := &HttpGetter{ Netrc: true, } - Getters = map[string]Getter{ + getters := map[string]Getter{ "file": new(FileGetter), "git": new(GitGetter), "gcs": new(GCSGetter), @@ -73,6 +75,11 @@ func init() { "http": httpGetter, "https": httpGetter, } + return getters +} + +func init() { + Getters = DefaultGetters() } // Get downloads the directory specified by src into the folder specified by