github.com/aclaygray/packer@v1.3.2/stdin.go (about) 1 package main 2 3 import ( 4 "io" 5 "log" 6 "os" 7 "os/signal" 8 "syscall" 9 ) 10 11 // setupStdin switches out stdin for a pipe. We do this so that we can 12 // close the writer end of the pipe when we receive an interrupt so plugins 13 // blocked on reading from stdin are unblocked. 14 func setupStdin() { 15 // Create the pipe and swap stdin for the reader end 16 r, w, _ := os.Pipe() 17 originalStdin := os.Stdin 18 os.Stdin = r 19 20 // Create a goroutine that copies data from the original stdin 21 // into the writer end of the pipe forever. 22 go func() { 23 defer w.Close() 24 io.Copy(w, originalStdin) 25 }() 26 27 // Register a signal handler for interrupt in order to close the 28 // writer end of our pipe so that readers get EOF downstream. 29 ch := make(chan os.Signal, 1) 30 signal.Notify(ch, os.Interrupt, syscall.SIGTERM) 31 32 go func() { 33 defer signal.Stop(ch) 34 defer w.Close() 35 <-ch 36 log.Println("Closing stdin because interrupt received.") 37 }() 38 }