Skip to content

Commit fa2efc4

Browse files
committed
Resolve docker.NewResolver race condition
Signed-off-by: Jin Dong <[email protected]> (cherry picked from commit cdb153e) Signed-off-by: Jin Dong <[email protected]>
1 parent f21a7a3 commit fa2efc4

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

remotes/docker/resolver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,11 @@ func NewResolver(options ResolverOptions) remotes.Resolver {
148148

149149
if options.Headers == nil {
150150
options.Headers = make(http.Header)
151+
} else {
152+
// make a copy of the headers to avoid race due to concurrent map write
153+
options.Headers = options.Headers.Clone()
151154
}
155+
152156
if _, ok := options.Headers["User-Agent"]; !ok {
153157
options.Headers.Set("User-Agent", "containerd/"+version.Version)
154158
}

remotes/docker/resolver_test.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,37 @@ func TestHTTPResolver(t *testing.T) {
4646
base := s.URL[7:] // strip "http://"
4747
return base, options, s.Close
4848
}
49-
5049
runBasicTest(t, "testname", s)
5150
}
5251

5352
func TestHTTPSResolver(t *testing.T) {
5453
runBasicTest(t, "testname", tlsServer)
5554
}
5655

56+
func TestResolverOptionsRace(t *testing.T) {
57+
header := http.Header{}
58+
header.Set("X-Test", "test")
59+
60+
s := func(h http.Handler) (string, ResolverOptions, func()) {
61+
s := httptest.NewServer(h)
62+
63+
options := ResolverOptions{
64+
Headers: header,
65+
}
66+
base := s.URL[7:] // strip "http://"
67+
return base, options, s.Close
68+
}
69+
70+
for i := 0; i < 5; i++ {
71+
t.Run(fmt.Sprintf("test ResolverOptions race %d", i), func(t *testing.T) {
72+
// parallel sub tests so the race condition (if not handled) can be caught
73+
// by race detector
74+
t.Parallel()
75+
runBasicTest(t, "testname", s)
76+
})
77+
}
78+
}
79+
5780
func TestBasicResolver(t *testing.T) {
5881
basicAuth := func(h http.Handler) (string, ResolverOptions, func()) {
5982
// Wrap with basic auth

0 commit comments

Comments
 (0)