Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit 84b2162

Browse files
committed
Set idle timeouts for HTTP reads and writes in communications with the registry
Otherwise, some operations can get stuck indefinitely when the remote side is unresponsive. Fixes #12823 Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
1 parent b5420be commit 84b2162

File tree

1 file changed

+40
-5
lines changed

1 file changed

+40
-5
lines changed

distribution/registry.go

+40-5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,30 @@ func (dcs dumbCredentialStore) Basic(*url.URL) (string, string) {
4545
return dcs.auth.Username, dcs.auth.Password
4646
}
4747

48+
// conn wraps a net.Conn, and sets a deadline for every read
49+
// and write operation.
50+
type conn struct {
51+
net.Conn
52+
readTimeout time.Duration
53+
writeTimeout time.Duration
54+
}
55+
56+
func (c *conn) Read(b []byte) (int, error) {
57+
err := c.Conn.SetReadDeadline(time.Now().Add(c.readTimeout))
58+
if err != nil {
59+
return 0, err
60+
}
61+
return c.Conn.Read(b)
62+
}
63+
64+
func (c *conn) Write(b []byte) (int, error) {
65+
err := c.Conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
66+
if err != nil {
67+
return 0, err
68+
}
69+
return c.Conn.Write(b)
70+
}
71+
4872
// NewV2Repository returns a repository (v2 only). It creates a HTTP transport
4973
// providing timeout settings and authentication support, and also verifies the
5074
// remote API version.
@@ -58,11 +82,22 @@ func NewV2Repository(ctx context.Context, repoInfo *registry.RepositoryInfo, end
5882
// TODO(dmcgowan): Call close idle connections when complete, use keep alive
5983
base := &http.Transport{
6084
Proxy: http.ProxyFromEnvironment,
61-
Dial: (&net.Dialer{
62-
Timeout: 30 * time.Second,
63-
KeepAlive: 30 * time.Second,
64-
DualStack: true,
65-
}).Dial,
85+
Dial: func(network, address string) (net.Conn, error) {
86+
dialer := &net.Dialer{
87+
Timeout: 30 * time.Second,
88+
KeepAlive: 30 * time.Second,
89+
DualStack: true,
90+
}
91+
netConn, err := dialer.Dial(network, address)
92+
if err != nil {
93+
return netConn, err
94+
}
95+
return &conn{
96+
Conn: netConn,
97+
readTimeout: time.Minute,
98+
writeTimeout: time.Minute,
99+
}, nil
100+
},
66101
TLSHandshakeTimeout: 10 * time.Second,
67102
TLSClientConfig: endpoint.TLSConfig,
68103
// TODO(dmcgowan): Call close idle connections when complete and use keep alive

0 commit comments

Comments
 (0)