@@ -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" )
0 commit comments