mirror of https://github.com/docker/compose.git
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:
parent
aefc2a111a
commit
1baa4f4489
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue