Skip to content

Commit

Permalink
fix: hoist signal handling from prompt confirmation
Browse files Browse the repository at this point in the history
Signed-off-by: Alano Terblanche <[email protected]>
  • Loading branch information
Benehiko committed Apr 8, 2024
1 parent c23a404 commit 13e4776
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 14 deletions.
10 changes: 1 addition & 9 deletions cli/command/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import (
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"runtime"
"strings"
"syscall"

"github.com/docker/cli/cli/streams"
"github.com/docker/docker/api/types/filters"
Expand Down Expand Up @@ -103,11 +101,6 @@ func PromptForConfirmation(ctx context.Context, ins io.Reader, outs io.Writer, m

result := make(chan bool)

// Catch the termination signal and exit the prompt gracefully.
// The caller is responsible for properly handling the termination.
notifyCtx, notifyCancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer notifyCancel()

go func() {
var res bool
scanner := bufio.NewScanner(ins)
Expand All @@ -121,8 +114,7 @@ func PromptForConfirmation(ctx context.Context, ins io.Reader, outs io.Writer, m
}()

select {
case <-notifyCtx.Done():
// print a newline on termination
case <-ctx.Done():
_, _ = fmt.Fprintln(outs, "")
return false, ErrPromptTerminated
case r := <-result:
Expand Down
6 changes: 5 additions & 1 deletion cli/command/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
Expand Down Expand Up @@ -135,6 +136,9 @@ func TestPromptForConfirmation(t *testing.T) {
}, promptResult{false, nil}},
} {
t.Run("case="+tc.desc, func(t *testing.T) {
notifyCtx, notifyCancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
t.Cleanup(notifyCancel)

buf.Reset()
promptReader, promptWriter = io.Pipe()

Expand All @@ -145,7 +149,7 @@ func TestPromptForConfirmation(t *testing.T) {

result := make(chan promptResult, 1)
go func() {
r, err := command.PromptForConfirmation(ctx, promptReader, promptOut, "")
r, err := command.PromptForConfirmation(notifyCtx, promptReader, promptOut, "")
result <- promptResult{r, err}
}()

Expand Down
7 changes: 6 additions & 1 deletion cmd/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,15 @@ func runDocker(ctx context.Context, dockerCli *command.DockerCli) error {
}
}

// Catch the termination signal and exit the prompt gracefully.
// The caller is responsible for properly handling the termination.
notifyCtx, notifyCancel := signal.NotifyContext(ctx, platformsignals.TerminationSignals...)
defer notifyCancel()

// We've parsed global args already, so reset args to those
// which remain.
cmd.SetArgs(args)
err = cmd.Execute()
err = cmd.ExecuteContext(notifyCtx)
if err != nil {
return err
}
Expand Down
8 changes: 5 additions & 3 deletions internal/test/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package test
import (
"context"
"os"
"syscall"
"testing"
"time"

Expand Down Expand Up @@ -32,8 +31,11 @@ func TerminatePrompt(ctx context.Context, t *testing.T, cmd *cobra.Command, cli
assert.NilError(t, err)
cli.SetIn(streams.NewIn(r))

notifyCtx, notifyCancel := context.WithCancel(ctx)
t.Cleanup(notifyCancel)

go func() {
errChan <- cmd.ExecuteContext(ctx)
errChan <- cmd.ExecuteContext(notifyCtx)
}()

writeCtx, writeCancel := context.WithTimeout(ctx, 100*time.Millisecond)
Expand Down Expand Up @@ -66,7 +68,7 @@ func TerminatePrompt(ctx context.Context, t *testing.T, cmd *cobra.Command, cli

// sigint and sigterm are caught by the prompt
// this allows us to gracefully exit the prompt with a 0 exit code
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
notifyCancel()

select {
case <-errCtx.Done():
Expand Down

0 comments on commit 13e4776

Please sign in to comment.