Skip to content

Commit 26a1841

Browse files
committed
response to comments
Signed-off-by: Nick Santos <[email protected]>
1 parent 36a3b0b commit 26a1841

2 files changed

Lines changed: 38 additions & 16 deletions

File tree

cli/command/cli.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ func WithInitializeClient(makeClient func(dockerCli *DockerCli) (client.APIClien
193193
}
194194
}
195195

196+
// WithInitializeTimeout is passed to DockerCli.Initialize by callers who wish to set a
197+
// timeout on the initial ping duration. The default is 2s.
198+
func WithInitializeTimeout(timeout time.Duration) InitializeOpt {
199+
return func(dockerCli *DockerCli) error {
200+
dockerCli.initTimeout = timeout
201+
return nil
202+
}
203+
}
204+
196205
// Initialize the dockerCli runs initialization that must happen after command
197206
// line flags are parsed.
198207
func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...InitializeOpt) error {
@@ -262,9 +271,6 @@ func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.
262271
}
263272

264273
func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigFile) (client.APIClient, error) {
265-
// NOTE(nick): Currently, this doesn't set any reasonable default timeouts, which
266-
// means that the CLI can hang forever on any operation. Repro steps:
267-
// https://github.com/docker/cli/issues/3652
268274
clientOpts, err := ep.ClientOpts()
269275
if err != nil {
270276
return nil, err

cli/command/cli_test.go

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/http"
1010
"net/http/httptest"
1111
"os"
12+
"path/filepath"
1213
"runtime"
1314
"strings"
1415
"testing"
@@ -170,20 +171,21 @@ func TestInitializeFromClient(t *testing.T) {
170171
// Makes sure we don't hang forever on the initial connection.
171172
// https://github.com/docker/cli/issues/3652
172173
func TestInitializeFromClientHangs(t *testing.T) {
173-
dir := fs.NewDir(t, t.Name())
174-
defer dir.Remove()
175-
176-
socket := dir.Join("my.sock")
174+
dir := t.TempDir()
175+
socket := filepath.Join(dir, "my.sock")
177176
l, err := net.Listen("unix", socket)
178177
assert.NilError(t, err)
179178

180-
received := false
181-
closeConn := make(chan struct{})
179+
receiveReqCh := make(chan bool)
180+
timeoutCtx, cancel := context.WithTimeout(context.Background(), time.Second)
181+
defer cancel()
182182

183183
// Simulate a server that hangs on connections.
184184
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
185-
received = true
186-
<-closeConn
185+
select {
186+
case <-timeoutCtx.Done():
187+
case receiveReqCh <- true: // Blocks until someone receives on the channel.
188+
}
187189
_, _ = w.Write([]byte("OK"))
188190
}))
189191
ts.Listener = l
@@ -195,11 +197,25 @@ func TestInitializeFromClientHangs(t *testing.T) {
195197
apiClient, err := NewAPIClientFromFlags(opts, configFile)
196198
assert.NilError(t, err)
197199

198-
cli := &DockerCli{client: apiClient}
199-
cli.initTimeout = time.Millisecond
200-
cli.Initialize(flags.NewClientOptions())
201-
assert.Assert(t, received)
202-
close(closeConn)
200+
initializedCh := make(chan bool)
201+
202+
go func() {
203+
cli := &DockerCli{client: apiClient}
204+
cli.Initialize(flags.NewClientOptions(), WithInitializeTimeout(time.Millisecond))
205+
close(initializedCh)
206+
}()
207+
208+
select {
209+
case <-timeoutCtx.Done():
210+
t.Fatal("timeout waiting for initialization to complete")
211+
case <-initializedCh:
212+
}
213+
214+
select {
215+
case <-timeoutCtx.Done():
216+
t.Fatal("server never received an init request")
217+
case <-receiveReqCh:
218+
}
203219
}
204220

205221
// The CLI no longer disables/hides experimental CLI features, however, we need

0 commit comments

Comments
 (0)