Skip to content

Commit

Permalink
Merge pull request #2745 from cbandy/quiet-canceled
Browse files Browse the repository at this point in the history
🐛 Quiet context.Canceled errors during shutdown
  • Loading branch information
k8s-ci-robot authored Aug 4, 2024
2 parents 5b943b9 + 5af1f3e commit 89b5dee
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
4 changes: 2 additions & 2 deletions pkg/manager/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,8 @@ func (cm *controllerManager) engageStopProcedure(stopComplete <-chan struct{}) e
cm.internalCancel()
})
select {
case err, ok := <-cm.errChan:
if ok {
case err := <-cm.errChan:
if !errors.Is(err, context.Canceled) {
cm.logger.Error(err, "error received after stop sequence was engaged")
}
case <-stopComplete:
Expand Down
52 changes: 52 additions & 0 deletions pkg/manager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"time"

"github.com/go-logr/logr"
"github.com/go-logr/logr/funcr"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -982,6 +983,57 @@ var _ = Describe("manger.Manager", func() {
}))).NotTo(Succeed())
})

It("should not return runnables context.Canceled errors", func() {
Expect(options.Logger).To(BeZero(), "this test overrides Logger")

var log struct {
sync.Mutex
messages []string
}
options.Logger = funcr.NewJSON(func(object string) {
log.Lock()
log.messages = append(log.messages, object)
log.Unlock()
}, funcr.Options{})

m, err := New(cfg, options)
Expect(err).NotTo(HaveOccurred())
for _, cb := range callbacks {
cb(m)
}

// Runnables may return ctx.Err() as shown in some [context.Context] examples.
started := make(chan struct{})
Expect(m.Add(RunnableFunc(func(ctx context.Context) error {
close(started)
<-ctx.Done()
return ctx.Err()
}))).To(Succeed())

stopped := make(chan error)
ctx, cancel := context.WithCancel(context.Background())
go func() {
stopped <- m.Start(ctx)
}()

// Wait for runnables to start, signal the manager, and wait for it to return.
<-started
cancel()
Expect(<-stopped).To(Succeed())

// The leader election goroutine emits one more log message after Start() returns.
// Take the lock here to avoid a race between it writing to log.messages and the
// following read from log.messages.
if options.LeaderElection {
log.Lock()
defer log.Unlock()
}

Expect(log.messages).To(Not(ContainElement(
ContainSubstring(context.Canceled.Error()),
)))
})

It("should return both runnables and stop errors when both error", func() {
m, err := New(cfg, options)
Expect(err).NotTo(HaveOccurred())
Expand Down

0 comments on commit 89b5dee

Please sign in to comment.