diff --git a/network/handlers/drain.go b/network/handlers/drain.go index 5eee2ea42e..3b2f28a077 100644 --- a/network/handlers/drain.go +++ b/network/handlers/drain.go @@ -196,7 +196,7 @@ func (d *Drainer) resetTimer() { d.Lock() defer d.Unlock() - if d.timer.Stop() { + if d.timer != nil && d.timer.Stop() { d.timer.Reset(d.QuietPeriod) } } diff --git a/network/handlers/drain_test.go b/network/handlers/drain_test.go index 082b8100d0..88e4f07e57 100644 --- a/network/handlers/drain_test.go +++ b/network/handlers/drain_test.go @@ -546,3 +546,43 @@ func TestReset(t *testing.T) { // Calling reset after a drain should succeed d.Reset() } + +// https://github.com/knative/pkg/issues/2642 +func TestResetWithActiveRequests(t *testing.T) { + d := Drainer{ + QuietPeriod: 5 * time.Second, + Inner: http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}), + } + + trafficStopped := make(chan struct{}) + trafficStarted := make(chan struct{}) + drainStarted := make(chan struct{}) + defer close(trafficStopped) + + go func() { + req, _ := http.NewRequest("GET", "knative.dev", nil) + rec := httptest.NewRecorder() + + close(trafficStarted) + for { + select { + case <-trafficStopped: + return + default: + d.ServeHTTP(rec, req) + } + } + }() + + go func() { + <-trafficStarted + close(drainStarted) + d.Drain() + }() + + <-drainStarted + d.Reset() + + // We need requests to be active for a bit + time.Sleep(time.Second) +}