// +build go1.3 package graceful import ( "net" "net/http" ) func (srv *Server) Serve(l net.Listener) error { l = WrapListener(l) // Spawn a shadow http.Server to do the actual servering. We do this // because we need to sketch on some of the parameters you passed in, // and it's nice to keep our sketching to ourselves. shadow := *(*http.Server)(srv) cs := shadow.ConnState shadow.ConnState = func(nc net.Conn, s http.ConnState) { if c, ok := nc.(*conn); ok { // There are a few other states defined, most notably // StateActive. Unfortunately it doesn't look like it's // possible to make use of StateActive to implement // graceful shutdown, since StateActive is set after a // complete request has been read off the wire with an // intent to process it. If we were to race a graceful // shutdown against a connection that was just read off // the wire (but not yet in StateActive), we would // accidentally close the connection out from underneath // an active request. // // We already needed to work around this for Go 1.2 by // shimming out a full net.Conn object, so we can just // fall back to the old behavior there. // // I started a golang-nuts thread about this here: // https://groups.google.com/forum/#!topic/golang-nuts/Xi8yjBGWfCQ // I'd be very eager to find a better way to do this, so // reach out to me if you have any ideas. switch s { case http.StateIdle: c.markIdle() case http.StateHijacked: c.hijack() } } if cs != nil { cs(nc, s) } } go func() { <-kill l.Close() shadow.SetKeepAlivesEnabled(false) idleSet.killall() }() err := shadow.Serve(l) // We expect an error when we close the listener, so we indiscriminately // swallow Serve errors when we're in a shutdown state. select { case <-kill: return nil default: return err } }