Fix reconfig freeze attempting to send to an unbuffered, unread channel (#886)

* Fixes a reocnfig freeze where the reconfig attempts to send to an unbuffered channel with no readers.
Only create stop channel when a DNS goroutine is created, and only send when the channel exists.
Buffer to size 1 so that the stop message can be immediately sent even if the goroutine is busy doing DNS lookups.
This commit is contained in:
brad-defined 2023-05-31 16:05:46 -04:00 committed by GitHub
parent 6d8c5f437c
commit 96f4dcaab8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 9 deletions

View file

@ -70,7 +70,7 @@ type hostnamesResults struct {
hostnames []hostnamePort
network string
lookupTimeout time.Duration
stop chan struct{}
cancelFn func()
l *logrus.Logger
ips atomic.Pointer[map[netip.AddrPort]struct{}]
}
@ -80,7 +80,6 @@ func NewHostnameResults(ctx context.Context, l *logrus.Logger, d time.Duration,
hostnames: make([]hostnamePort, len(hostPorts)),
network: network,
lookupTimeout: timeout,
stop: make(chan (struct{})),
l: l,
}
@ -115,6 +114,8 @@ func NewHostnameResults(ctx context.Context, l *logrus.Logger, d time.Duration,
// Time for the DNS lookup goroutine
if performBackgroundLookup {
newCtx, cancel := context.WithCancel(ctx)
r.cancelFn = cancel
ticker := time.NewTicker(d)
go func() {
defer ticker.Stop()
@ -154,9 +155,7 @@ func NewHostnameResults(ctx context.Context, l *logrus.Logger, d time.Duration,
onUpdate()
}
select {
case <-ctx.Done():
return
case <-r.stop:
case <-newCtx.Done():
return
case <-ticker.C:
continue
@ -169,8 +168,8 @@ func NewHostnameResults(ctx context.Context, l *logrus.Logger, d time.Duration,
}
func (hr *hostnamesResults) Cancel() {
if hr != nil {
hr.stop <- struct{}{}
if hr != nil && hr.cancelFn != nil {
hr.cancelFn()
}
}