I am looking for the safe way to do a clean shutdown when blocked on I/O. Here is a basic example:
package main import ( "encoding/json" "fmt" "io" "os" "os/signal" "syscall" ) func main() { rx := json.NewDecoder(os.Stdin) chanTERM := make(chan os.Signal, 1) signal.Notify(chanTERM, syscall.SIGTERM) for { select { case <-chanTERM: fmt.Println("Shutdown requested via signal") os.Exit(0) default: } var msg interface{} err := rx.Decode(&msg) if err != nil { if err == io.EOF { os.Exit(0) } fmt.Printf("Error: %v\n", err) os.Exit(1) } fmt.Printf("Message: %v\n", msg) } } This sort-of works, except that once the code is blocked in rx.Decode(&msg), the termination signal is not handled until another message arrives. (Actually I'm using sockets - os.Stdin is just for example here). I'd like it to shutdown immediately if it's not in the middle of doing something. The question is then how to unblock this reader. 1. Is there a way to link an io.Reader to a context, so I can just send the ctx.Done() signal? If so, I couldn't find it. (I found this post <https://pace.dev/blog/2020/02/03/context-aware-ioreader-for-golang-by-mat-ryer.html>, but the library <https://github.com/dolmen-go/contextio/blob/68fc5150bcd5/io.go#L66> has the same issue: the context is checked before the read, but a cancel won't unblock the read) 2. I can just close the input stream from another goroutine. This seems fairly brutal. Also, to distinguish this condition from an actual error, it seems I need to parse the error message and look for the text "use of closed network connection" (github: #4373 <https://github.com/golang/go/issues/4373>) 3. I can move the rx.Decode(&msg) into a goroutine which passes a message over a channel, and just let it lock up if there's no data coming in. This isn't a problem here where I want to exit the entire program. If this was a network server with many connections and I wanted to disconnect just one, then I think I'd end up having to close the channel anyway to disconnect the client. Is there another option I should be looking at? Thanks, Brian. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/3f3b6f98-ff9c-4829-844b-a0d0abc5d753o%40googlegroups.com.