mirror of https://github.com/knative/pkg.git
fix double close of channel (#2574)
This commit is contained in:
parent
f78a006943
commit
766f70d9cb
|
|
@ -73,8 +73,11 @@ type Drainer struct {
|
||||||
// timer is used to orchestrate the drain.
|
// timer is used to orchestrate the drain.
|
||||||
timer timer
|
timer timer
|
||||||
|
|
||||||
// used to synchronize callers of Drain and Reset
|
// used to synchronize callers of Drain
|
||||||
ch chan struct{}
|
drainCh chan struct{}
|
||||||
|
|
||||||
|
// used to synchronize Drain and Reset
|
||||||
|
resetCh chan struct{}
|
||||||
|
|
||||||
// HealthCheckUAPrefixes are the additional user agent prefixes that trigger the
|
// HealthCheckUAPrefixes are the additional user agent prefixes that trigger the
|
||||||
// drainer's health check
|
// drainer's health check
|
||||||
|
|
@ -118,8 +121,8 @@ func (d *Drainer) Drain() {
|
||||||
ch := func() chan struct{} {
|
ch := func() chan struct{} {
|
||||||
d.Lock()
|
d.Lock()
|
||||||
defer d.Unlock()
|
defer d.Unlock()
|
||||||
if d.ch != nil {
|
if d.drainCh != nil {
|
||||||
return d.ch
|
return d.drainCh
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.QuietPeriod <= 0 {
|
if d.QuietPeriod <= 0 {
|
||||||
|
|
@ -127,32 +130,26 @@ func (d *Drainer) Drain() {
|
||||||
}
|
}
|
||||||
|
|
||||||
timer := newTimer(d.QuietPeriod)
|
timer := newTimer(d.QuietPeriod)
|
||||||
ch := make(chan struct{})
|
drainCh := make(chan struct{})
|
||||||
|
resetCh := make(chan struct{})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-ch:
|
case <-resetCh:
|
||||||
// closed by reset
|
|
||||||
case <-timer.tickChan():
|
case <-timer.tickChan():
|
||||||
close(ch)
|
|
||||||
}
|
}
|
||||||
|
close(drainCh)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
d.ch = ch
|
d.drainCh = drainCh
|
||||||
|
d.resetCh = resetCh
|
||||||
d.timer = timer
|
d.timer = timer
|
||||||
return ch
|
return drainCh
|
||||||
}()
|
}()
|
||||||
|
|
||||||
<-ch
|
<-ch
|
||||||
}
|
}
|
||||||
|
|
||||||
func drainTimer(tc <-chan time.Time) {
|
|
||||||
select {
|
|
||||||
case <-tc:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// isHealthcheckRequest validates if the request has a user agent that is for healthcheck
|
// isHealthcheckRequest validates if the request has a user agent that is for healthcheck
|
||||||
func (d *Drainer) isHealthCheckRequest(r *http.Request) bool {
|
func (d *Drainer) isHealthCheckRequest(r *http.Request) bool {
|
||||||
if network.IsKubeletProbe(r) {
|
if network.IsKubeletProbe(r) {
|
||||||
|
|
@ -175,16 +172,16 @@ func (d *Drainer) Reset() {
|
||||||
defer d.Unlock()
|
defer d.Unlock()
|
||||||
|
|
||||||
if d.timer != nil {
|
if d.timer != nil {
|
||||||
if d.timer.Stop() {
|
d.timer.Stop()
|
||||||
d.timer = nil
|
d.timer = nil
|
||||||
} else {
|
|
||||||
drainTimer(d.timer.tickChan())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.ch != nil {
|
if d.resetCh != nil {
|
||||||
close(d.ch)
|
close(d.resetCh)
|
||||||
d.ch = nil
|
d.resetCh = nil
|
||||||
|
}
|
||||||
|
if d.drainCh != nil {
|
||||||
|
d.drainCh = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -542,4 +542,7 @@ func TestReset(t *testing.T) {
|
||||||
if diff > 50*time.Millisecond {
|
if diff > 50*time.Millisecond {
|
||||||
t.Error("expected to drain to wait QuietPeriod time after reset")
|
t.Error("expected to drain to wait QuietPeriod time after reset")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calling reset after a drain should succeed
|
||||||
|
d.Reset()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue