diff --git a/cmd/event/consume.go b/cmd/event/consume.go index 9fd4d234d..fdc6fad49 100644 --- a/cmd/event/consume.go +++ b/cmd/event/consume.go @@ -184,8 +184,9 @@ func runConsume(cmd *cobra.Command, f *cmdutil.Factory, eventKey string, o consu errOut = io.Discard } - // Non-TTY only: stdin EOF is shutdown for subprocess callers; in TTY Ctrl-D must not exit. - if !f.IOStreams.IsTerminal { + // Non-TTY unbounded consumers use stdin EOF as shutdown for subprocess callers. + // Bounded runs already have --max-events/--timeout as their lifecycle control. + if shouldWatchStdinEOF(f.IOStreams.IsTerminal, o.maxEvents, o.timeout) { watchStdinEOF(os.Stdin, cancel, errOut) } @@ -370,3 +371,7 @@ func watchStdinEOF(r io.Reader, cancel context.CancelFunc, errOut io.Writer) { cancel() }() } + +func shouldWatchStdinEOF(isTerminal bool, maxEvents int, timeout time.Duration) bool { + return !isTerminal && maxEvents <= 0 && timeout <= 0 +} diff --git a/cmd/event/consume_stdin_test.go b/cmd/event/consume_stdin_test.go index c4391842c..de2a2e2e1 100644 --- a/cmd/event/consume_stdin_test.go +++ b/cmd/event/consume_stdin_test.go @@ -61,3 +61,52 @@ func TestWatchStdinEOF_DiagnosticMessage(t *testing.T) { t.Fatal("watchStdinEOF did not cancel within 1s of EOF") } } + +func TestShouldWatchStdinEOF(t *testing.T) { + tests := []struct { + name string + isTerminal bool + maxEvents int + timeout time.Duration + want bool + }{ + { + name: "terminal", + isTerminal: true, + want: false, + }, + { + name: "non terminal unbounded", + want: true, + }, + { + name: "non terminal negative max events is unbounded", + maxEvents: -1, + want: true, + }, + { + name: "non terminal negative timeout is unbounded", + timeout: -1 * time.Second, + want: true, + }, + { + name: "non terminal max events bounded", + maxEvents: 1, + want: false, + }, + { + name: "non terminal timeout bounded", + timeout: 10 * time.Minute, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := shouldWatchStdinEOF(tt.isTerminal, tt.maxEvents, tt.timeout) + if got != tt.want { + t.Fatalf("shouldWatchStdinEOF() = %v, want %v", got, tt.want) + } + }) + } +}