@@ -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.
@@ -304,8 +307,24 @@ func Main(opts ...Option) error {
304307 case <- d .Ctx .Done ():
305308 logger .Info ("Received TERM signal, attempting to gracefully shutdown servers." )
306309 logger .Infof ("Sleeping %v to allow K8s propagation of non-ready state" , drainSleepDuration )
310+ time .Sleep (drainSleepDuration )
307311 drainer .Drain ()
308312
313+ // Wait on active requests to complete. This is done explictly
314+ // to avoid closing any connections which have been highjacked,
315+ // as in net/http `.Shutdown` would do so ungracefully.
316+ // See https://github.com/golang/go/issues/17721
317+ ticker := time .NewTicker (1 * time .Second )
318+ defer ticker .Stop ()
319+ logger .Infof ("Drain: waiting for %d pending requests to complete" , pendingRequests .Load ())
320+ WaitOnPendingRequests:
321+ for range ticker .C {
322+ if pendingRequests .Load () <= 0 {
323+ logger .Infof ("Drain: all pending requests completed" )
324+ break WaitOnPendingRequests
325+ }
326+ }
327+
309328 for name , srv := range httpServers {
310329 logger .Info ("Shutting down server: " , name )
311330 if err := srv .Shutdown (context .Background ()); err != nil {
0 commit comments