Can you write your own ContextReader that checks ctx.Done in its Read method?
On Mon, 6 Jul 2020, at 2:40 PM, Brian Candler wrote:
> 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
>
> <https://groups.google.com/d/msgid/golang-nuts/3f3b6f98-ff9c-4829-844b-a0d0abc5d753o%40googlegroups.com?utm_medium=email&utm_source=footer>.
--
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/d1c9f0d0-dbb3-4730-997d-2e13155509b6%40www.fastmail.com.