Goroutine already started in Go web server from request but client disconnects, is it possible for a web server to close that particular goroutine?

Issue

Whenever a web request comes in from the client it would spawn a goroutine to handle each. If the client just happen to disconnect from the connection, is it possible for a web server to close that particular goroutine or will that goroutine find out that the client had already diconnected after it had executed all its code?

Solution

Other than exiting on the return from a called handler on a read or write error – the executing go routine will not automatically handle cleaning up longer running operations, but Go provides nice ways of handling this.

First, if you are not familiar with the context package – it is a powerful and idiomatic way to synchronize go routines with cancellation behavior, I highly recommend reading the blog Go Concurrency Patterns: Context.

Something like the following:

func MyServiceFunc(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            break
        default:
            //do work
        }
    }
}

func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
    MyServiceFunc(req.Context())       
   //write response...
}

Or you could use the CloseNotifier interface of which a http.ResponseWriter also implements, you could do something like the following simple example:

func MyServiceFunc(notifier <-chan bool) {
    for {
        select {
        case <-notifier:
            break
        default:
            //do work
        }
    }
}


func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
    notifier := res.(http.CloseNotifier).CloseNotify()
    MyServiceFunc(notifier)
    //write response...
}

Or, and simple example using combining both approaches:

func MyRequestHandler(res http.ResponseWriter, req *http.Request) {

    notifier := res.(http.CloseNotifier).CloseNotify()
    ctx, cancel := context.WithCancel(req.Context())

    go func(closer <-chan bool) {
        <-closer //the notifer blocks until the send
        cancel() //explicitly cancel all go routines
    }(notifier)

    go MyServiceFunc(ctx)
    MyOtherServiceFunc(ctx)
    //write response...
}

Answered By – syllabix

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.