mirror of
https://github.com/coredns/coredns.git
synced 2026-07-17 13:10:11 -04:00
plugin/secondary: stop update loop on reload shutdown (#8198)
This commit is contained in:
@@ -116,11 +116,16 @@ func less(a, b uint32) bool {
|
||||
func (z *Zone) Update(updateShutdown chan bool, t *transfer.Transfer) error {
|
||||
// If we don't have a SOA, we don't have a zone, wait for it to appear.
|
||||
for z.getSOA() == nil {
|
||||
time.Sleep(1 * time.Second)
|
||||
if waitOrShutdown(updateShutdown, time.Second) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
retryActive := false
|
||||
|
||||
Restart:
|
||||
if updateStopped(updateShutdown) {
|
||||
return nil
|
||||
}
|
||||
soa := z.getSOA()
|
||||
refresh := time.Second * time.Duration(soa.Refresh)
|
||||
retry := time.Second * time.Duration(soa.Retry)
|
||||
@@ -145,7 +150,10 @@ Restart:
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(jitter(2000)) // 2s randomize
|
||||
if waitOrShutdown(updateShutdown, jitter(2000)) { // 2s randomize
|
||||
stopUpdateTickers(refreshTicker, retryTicker, expireTicker)
|
||||
return nil
|
||||
}
|
||||
|
||||
ok, err := z.shouldTransfer()
|
||||
if err != nil {
|
||||
@@ -162,14 +170,15 @@ Restart:
|
||||
|
||||
// no errors, stop timers and restart
|
||||
retryActive = false
|
||||
refreshTicker.Stop()
|
||||
retryTicker.Stop()
|
||||
expireTicker.Stop()
|
||||
stopUpdateTickers(refreshTicker, retryTicker, expireTicker)
|
||||
goto Restart
|
||||
|
||||
case <-refreshTicker.C:
|
||||
|
||||
time.Sleep(jitter(5000)) // 5s randomize
|
||||
if waitOrShutdown(updateShutdown, jitter(5000)) { // 5s randomize
|
||||
stopUpdateTickers(refreshTicker, retryTicker, expireTicker)
|
||||
return nil
|
||||
}
|
||||
|
||||
ok, err := z.shouldTransfer()
|
||||
if err != nil {
|
||||
@@ -188,20 +197,45 @@ Restart:
|
||||
|
||||
// no errors, stop timers and restart
|
||||
retryActive = false
|
||||
refreshTicker.Stop()
|
||||
retryTicker.Stop()
|
||||
expireTicker.Stop()
|
||||
stopUpdateTickers(refreshTicker, retryTicker, expireTicker)
|
||||
goto Restart
|
||||
|
||||
case <-updateShutdown:
|
||||
refreshTicker.Stop()
|
||||
retryTicker.Stop()
|
||||
expireTicker.Stop()
|
||||
stopUpdateTickers(refreshTicker, retryTicker, expireTicker)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func waitOrShutdown(updateShutdown <-chan bool, d time.Duration) bool {
|
||||
if updateStopped(updateShutdown) {
|
||||
return true
|
||||
}
|
||||
timer := time.NewTimer(d)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case <-timer.C:
|
||||
return false
|
||||
case <-updateShutdown:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func updateStopped(updateShutdown <-chan bool) bool {
|
||||
select {
|
||||
case <-updateShutdown:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func stopUpdateTickers(tickers ...*time.Ticker) {
|
||||
for _, ticker := range tickers {
|
||||
ticker.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// jitter returns a random duration between [0,n) * time.Millisecond
|
||||
func jitter(n int) time.Duration {
|
||||
r := rand.Intn(n) // #nosec G404 -- non-cryptographic jitter to spread transfer attempts.
|
||||
|
||||
@@ -3,6 +3,7 @@ package file
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
||||
"github.com/coredns/coredns/plugin/test"
|
||||
@@ -121,6 +122,27 @@ func TestTransferIn(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateStopsBeforeInitialTransfer(t *testing.T) {
|
||||
z := NewZone(testZone, "test")
|
||||
updateShutdown := make(chan bool)
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
if err := z.Update(updateShutdown, nil); err != nil {
|
||||
t.Errorf("Unexpected update error: %v", err)
|
||||
}
|
||||
close(done)
|
||||
}()
|
||||
|
||||
close(updateShutdown)
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(200 * time.Millisecond):
|
||||
t.Fatal("Update did not stop while waiting for initial SOA")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsNotify(t *testing.T) {
|
||||
z := new(Zone)
|
||||
z.origin = testZone
|
||||
|
||||
Reference in New Issue
Block a user