up: fix write/close race condition in logPrinter

The code used an atomic bool to guard channel writes. However, this
failed to synchronize with the call to close(), causing a panic.

Fix the race condition by using a mutex to guard the update to the
bool `stopped` and subsequent channel writes. This ensures atomic
execution of both updates to `stopped` and channel writes, preventing
races between writes and close().

Signed-off-by: horus <horus.li@gmail.com>
This commit is contained in:
horus 2023-12-19 21:55:04 +08:00 committed by Nicolas De loof
parent aefc2a111a
commit 1baa4f4489
1 changed files with 12 additions and 6 deletions

View File

@ -18,7 +18,7 @@ package compose
import (
"fmt"
"sync/atomic"
"sync"
"github.com/docker/compose/v2/pkg/api"
)
@ -32,9 +32,10 @@ type logPrinter interface {
}
type printer struct {
sync.Mutex
queue chan api.ContainerEvent
consumer api.LogConsumer
stopped atomic.Bool
stopped bool
}
// newLogPrinter builds a LogPrinter passing containers logs to LogConsumer
@ -53,16 +54,21 @@ func (p *printer) Cancel() {
}
func (p *printer) Stop() {
if p.stopped.CompareAndSwap(false, true) {
p.Lock()
defer p.Unlock()
if !p.stopped {
// only close if this is the first call to stop
p.stopped = true
close(p.queue)
}
}
func (p *printer) HandleEvent(event api.ContainerEvent) {
// prevent deadlocking, if the printer is done, there's no reader for
// queue, so this write could block indefinitely
if p.stopped.Load() {
p.Lock()
defer p.Unlock()
if p.stopped {
// prevent deadlocking, if the printer is done, there's no reader for
// queue, so this write could block indefinitely
return
}
p.queue <- event