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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/3f3b6f98-ff9c-4829-844b-a0d0abc5d753o%40googlegroups.com.