Skip to content

Commit 219d25e

Browse files
mrnuggetBolajiOlajide
authored andcommitted
Cancel reading from stdin on Ctrl-C
This is essentially a copy-paste implementation of the ideas presented in this comment here: golang/go#20280 (comment) It fixes #775 and helps with the issue described in #793 (comment). Not sure if it has unintended side-effects.
1 parent 05e3f02 commit 219d25e

File tree

4 files changed

+28
-7
lines changed

4 files changed

+28
-7
lines changed

cmd/src/batch_common.go

+25-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"path/filepath"
1313
"runtime"
1414
"strings"
15+
"syscall"
1516
"time"
1617

1718
"github.com/mattn/go-isatty"
@@ -220,7 +221,7 @@ func batchDefaultTempDirPrefix() string {
220221
return os.TempDir()
221222
}
222223

223-
func batchOpenFileFlag(flag string) (io.ReadCloser, error) {
224+
func batchOpenFileFlag(flag string) (*os.File, error) {
224225
if flag == "" || flag == "-" {
225226
if flag != "-" {
226227
// If the flag wasn't set, we want to check stdin. If it's not a TTY,
@@ -238,8 +239,13 @@ func batchOpenFileFlag(flag string) (io.ReadCloser, error) {
238239
}
239240
}
240241
}
242+
// https://github.com/golang/go/issues/24842
243+
if err := syscall.SetNonblock(0, true); err != nil {
244+
panic(err)
245+
}
246+
stdin := os.NewFile(0, "stdin")
241247

242-
return os.Stdin, nil
248+
return stdin, nil
243249
}
244250

245251
file, err := os.Open(flag)
@@ -292,7 +298,7 @@ func executeBatchSpec(ctx context.Context, ui ui.ExecUI, opts executeBatchSpecOp
292298

293299
// Parse flags and build up our service and executor options.
294300
ui.ParsingBatchSpec()
295-
batchSpec, rawSpec, err := parseBatchSpec(opts.file, svc, false)
301+
batchSpec, rawSpec, err := parseBatchSpec(ctx, opts.file, svc, false)
296302
if err != nil {
297303
var multiErr errors.MultiError
298304
if errors.As(err, &multiErr) {
@@ -481,18 +487,33 @@ func executeBatchSpec(ctx context.Context, ui ui.ExecUI, opts executeBatchSpecOp
481487
return nil
482488
}
483489

490+
type ReadDeadliner interface {
491+
SetReadDeadline(t time.Time) error
492+
}
493+
494+
func SetReadDeadlineOnCancel(ctx context.Context, d ReadDeadliner) {
495+
go func() {
496+
<-ctx.Done()
497+
d.SetReadDeadline(time.Now())
498+
}()
499+
}
500+
484501
// parseBatchSpec parses and validates the given batch spec. If the spec has
485502
// validation errors, they are returned.
486503
//
487504
// isRemote argument is a temporary argument used to determine if the batch spec is being parsed for remote
488505
// (server-side) processing. Remote processing does not support mounts yet.
489-
func parseBatchSpec(file string, svc *service.Service, isRemote bool) (*batcheslib.BatchSpec, string, error) {
506+
func parseBatchSpec(ctx context.Context, file string, svc *service.Service, isRemote bool) (*batcheslib.BatchSpec, string, error) {
490507
f, err := batchOpenFileFlag(file)
491508
if err != nil {
492509
return nil, "", err
493510
}
494511
defer f.Close()
495512

513+
ctx, cancel := context.WithCancel(ctx)
514+
defer cancel()
515+
SetReadDeadlineOnCancel(ctx, f)
516+
496517
data, err := io.ReadAll(f)
497518
if err != nil {
498519
return nil, "", errors.Wrap(err, "reading batch spec")

cmd/src/batch_remote.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Examples:
6363
// may as well validate it at the same time so we don't even have to go to
6464
// the backend if it's invalid.
6565
ui.ParsingBatchSpec()
66-
spec, raw, err := parseBatchSpec(file, svc, true)
66+
spec, raw, err := parseBatchSpec(ctx, file, svc, true)
6767
if err != nil {
6868
ui.ParsingBatchSpecFailure(err)
6969
return err

cmd/src/batch_repositories.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ Examples:
7575
}
7676

7777
out := output.NewOutput(flagSet.Output(), output.OutputOpts{Verbose: *verbose})
78-
spec, _, err := parseBatchSpec(file, svc, false)
78+
spec, _, err := parseBatchSpec(ctx, file, svc, false)
7979
if err != nil {
8080
ui := &ui.TUI{Out: out}
8181
ui.ParsingBatchSpecFailure(err)

cmd/src/batch_validate.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ Examples:
7575
return err
7676
}
7777

78-
if _, _, err := parseBatchSpec(file, svc, false); err != nil {
78+
if _, _, err := parseBatchSpec(ctx, file, svc, false); err != nil {
7979
ui.ParsingBatchSpecFailure(err)
8080
return err
8181
}

0 commit comments

Comments
 (0)