Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c9d3b2c

Browse files
committed
fix: agentcontainers: fix flake when ctx cancelled while running docker inspect
1 parent 670fa4a commit c9d3b2c

File tree

2 files changed

+33
-15
lines changed

2 files changed

+33
-15
lines changed

agent/agentcontainers/api.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,11 @@ func (api *API) updaterLoop() {
378378
// and anyone looking to interact with the API.
379379
api.logger.Debug(api.ctx, "performing initial containers update")
380380
if err := api.updateContainers(api.ctx); err != nil {
381-
api.logger.Error(api.ctx, "initial containers update failed", slog.Error(err))
381+
if errors.Is(err, context.Canceled) {
382+
api.logger.Warn(api.ctx, "initial containers update canceled", slog.Error(err))
383+
} else {
384+
api.logger.Error(api.ctx, "initial containers update failed", slog.Error(err))
385+
}
382386
} else {
383387
api.logger.Debug(api.ctx, "initial containers update complete")
384388
}
@@ -399,7 +403,11 @@ func (api *API) updaterLoop() {
399403
case api.updateTrigger <- done:
400404
err := <-done
401405
if err != nil {
402-
api.logger.Error(api.ctx, "updater loop ticker failed", slog.Error(err))
406+
if errors.Is(err, context.Canceled) {
407+
api.logger.Warn(api.ctx, "updater loop ticker canceled", slog.Error(err))
408+
} else {
409+
api.logger.Error(api.ctx, "updater loop ticker failed", slog.Error(err))
410+
}
403411
}
404412
default:
405413
api.logger.Debug(api.ctx, "updater loop ticker skipped, update in progress")

agent/agentcontainers/containers_dockercli.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -311,21 +311,31 @@ func (dcli *dockerCLI) List(ctx context.Context) (codersdk.WorkspaceAgentListCon
311311
// container IDs and returns the parsed output.
312312
// The stderr output is also returned for logging purposes.
313313
func runDockerInspect(ctx context.Context, execer agentexec.Execer, ids ...string) (stdout, stderr []byte, err error) {
314-
var stdoutBuf, stderrBuf bytes.Buffer
315-
cmd := execer.CommandContext(ctx, "docker", append([]string{"inspect"}, ids...)...)
316-
cmd.Stdout = &stdoutBuf
317-
cmd.Stderr = &stderrBuf
318-
err = cmd.Run()
319-
stdout = bytes.TrimSpace(stdoutBuf.Bytes())
320-
stderr = bytes.TrimSpace(stderrBuf.Bytes())
321-
if err != nil {
322-
if bytes.Contains(stderr, []byte("No such object:")) {
323-
// This can happen if a container is deleted between the time we check for its existence and the time we inspect it.
324-
return stdout, stderr, nil
314+
select {
315+
case <-ctx.Done():
316+
// If the context is done, we don't want to run the command.
317+
return []byte{}, []byte{}, ctx.Err()
318+
default:
319+
var stdoutBuf, stderrBuf bytes.Buffer
320+
cmd := execer.CommandContext(ctx, "docker", append([]string{"inspect"}, ids...)...)
321+
cmd.Stdout = &stdoutBuf
322+
cmd.Stderr = &stderrBuf
323+
err = cmd.Run()
324+
stdout = bytes.TrimSpace(stdoutBuf.Bytes())
325+
stderr = bytes.TrimSpace(stderrBuf.Bytes())
326+
if err != nil {
327+
if ctx.Err() != nil {
328+
// If the context was canceled, we don't want to return an error.
329+
return stdout, stderr, ctx.Err()
330+
}
331+
if bytes.Contains(stderr, []byte("No such object:")) {
332+
// This can happen if a container is deleted between the time we check for its existence and the time we inspect it.
333+
return stdout, stderr, nil
334+
}
335+
return stdout, stderr, err
325336
}
326-
return stdout, stderr, err
337+
return stdout, stderr, nil
327338
}
328-
return stdout, stderr, nil
329339
}
330340

331341
// To avoid a direct dependency on the Docker API, we use the docker CLI

0 commit comments

Comments
 (0)