I'd like to read user-input in go and ignore the user's attempts to kill my process by trapping CTRL-C.
I spin a goroutine to trap CTRL-C
and also write to a channel. At this stage, I expect control to return to case <-intr
in the main goroutine, but that's not happening.
Here's output from a run:
$ go run read.go
Enter text: hello
Entered:hello
$go run read.go
Enter text: ^CGot signal interrupt
Exiting signal handler..
Invalid input2
Interrupted.. Continuing
Enter text: ^C
Invalid input2
Enter text: ^C
Invalid input2
Enter text: ^C^C^C^C
Invalid input2
Enter text: ^C
Invalid input2
Enter text: ^C
Invalid input2
Enter text:
The first CTRL-C is trapped alright and soon after it exits, it appears that the main goroutine is executing r := bufio.NewReader(os.Stdin)
When I hit CTRL-C as input later, it is simply treated as text and the signal handler isn't invoked.
My code is below (goplay link: http://play.golang.org/p/LiKZMYGr00)
package main
import ("fmt"
"bufio"
"os"
"os/signal"
"syscall"
"io"
"strings"
)
func main() {
c := make(chan os.Signal)
intr := make(chan bool)
signal.Notify(c, syscall.SIGINT)
go func() {
s := <-c
fmt.Println("Got signal", s)
fmt.Println("Exiting signal handler..")
intr <- true
return
}()
breakOutOfHere:
for {
select {
case <-intr:
fmt.Println("Interrupted.. Continuing")
continue
default:
fmt.Printf("Enter text: ")
r := bufio.NewReader(os.Stdin)
text, ret := r.ReadString('
')
if ret == io.EOF {
fmt.Println("Invalid input1")
continue
} else if ret == nil {
text = strings.TrimSpace(text)
if text == "" {
fmt.Println("Invalid input2")
continue
} else {
fmt.Printf("Entered:%s
", text)
break breakOutOfHere
}
}
}
}
}