@@ -24,6 +24,7 @@ import (
2424 "net/http"
2525 "os"
2626 "strconv"
27+ "sync/atomic"
2728 "time"
2829
2930 "github.com/kelseyhightower/envconfig"
@@ -169,6 +170,8 @@ func Main(opts ...Option) error {
169170 d := Defaults {
170171 Ctx : signals .NewContext (),
171172 }
173+ pendingRequests := atomic.Int32 {}
174+ pendingRequests .Store (0 )
172175
173176 // Parse the environment.
174177 var env config
@@ -234,7 +237,7 @@ func Main(opts ...Option) error {
234237 // Enable TLS when certificate is mounted.
235238 tlsEnabled := exists (logger , certPath ) && exists (logger , keyPath )
236239
237- mainHandler , drainer := mainHandler (d .Ctx , env , d .Transport , probe , stats , logger )
240+ mainHandler , drainer := mainHandler (d .Ctx , env , d .Transport , probe , stats , logger , & pendingRequests )
238241 adminHandler := adminHandler (d .Ctx , logger , drainer )
239242
240243 // Enable TLS server when activator server certs are mounted.
@@ -303,9 +306,23 @@ func Main(opts ...Option) error {
303306 return err
304307 case <- d .Ctx .Done ():
305308 logger .Info ("Received TERM signal, attempting to gracefully shutdown servers." )
306- logger .Infof ("Sleeping %v to allow K8s propagation of non-ready state" , drainSleepDuration )
307309 drainer .Drain ()
308310
311+ // Wait on active requests to complete. This is done explictly
312+ // to avoid closing any connections which have been highjacked,
313+ // as in net/http `.Shutdown` would do so ungracefully.
314+ // See https://github.com/golang/go/issues/17721
315+ ticker := time .NewTicker (1 * time .Second )
316+ defer ticker .Stop ()
317+ logger .Infof ("Drain: waiting for %d pending requests to complete" , pendingRequests .Load ())
318+ WaitOnPendingRequests:
319+ for range ticker .C {
320+ if pendingRequests .Load () <= 0 {
321+ logger .Infof ("Drain: all pending requests completed" )
322+ break WaitOnPendingRequests
323+ }
324+ }
325+
309326 for name , srv := range httpServers {
310327 logger .Info ("Shutting down server: " , name )
311328 if err := srv .Shutdown (context .Background ()); err != nil {
0 commit comments