From 315967f32d4c954447e17a1806045855ebad94d0 Mon Sep 17 00:00:00 2001 From: Donald Nguyen Date: Thu, 15 Sep 2022 01:15:42 -0700 Subject: [PATCH] Avoid race in diode.Close with waiter (#481) --- diode/diode_test.go | 8 ++++++++ diode/internal/diodes/waiter.go | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/diode/diode_test.go b/diode/diode_test.go index 098bd44..d0d0aff 100644 --- a/diode/diode_test.go +++ b/diode/diode_test.go @@ -30,6 +30,14 @@ func TestNewWriter(t *testing.T) { } } +func TestClose(t *testing.T) { + buf := bytes.Buffer{} + w := diode.NewWriter(&buf, 1000, 0, func(missed int) {}) + log := zerolog.New(w) + log.Print("test") + w.Close() +} + func Benchmark(b *testing.B) { log.SetOutput(ioutil.Discard) defer log.SetOutput(os.Stderr) diff --git a/diode/internal/diodes/waiter.go b/diode/internal/diodes/waiter.go index 7c9bb0c..a4a8e97 100644 --- a/diode/internal/diodes/waiter.go +++ b/diode/internal/diodes/waiter.go @@ -39,7 +39,12 @@ func NewWaiter(d Diode, opts ...WaiterConfigOption) *Waiter { go func() { <-w.ctx.Done() + + // Mutex is strictly necessary here to avoid a race in Next() (between + // w.isDone() and w.c.Wait()) and w.c.Broadcast() here. + w.mu.Lock() w.c.Broadcast() + w.mu.Unlock() }() return w