mirror of
https://github.com/docker/compose.git
synced 2025-07-31 01:24:15 +02:00
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync/atomic"
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
)
|
)
|
||||||
@ -32,9 +32,10 @@ type logPrinter interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type printer struct {
|
type printer struct {
|
||||||
|
sync.Mutex
|
||||||
queue chan api.ContainerEvent
|
queue chan api.ContainerEvent
|
||||||
consumer api.LogConsumer
|
consumer api.LogConsumer
|
||||||
stopped atomic.Bool
|
stopped bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLogPrinter builds a LogPrinter passing containers logs to LogConsumer
|
// newLogPrinter builds a LogPrinter passing containers logs to LogConsumer
|
||||||
@ -53,16 +54,21 @@ func (p *printer) Cancel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *printer) Stop() {
|
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
|
// only close if this is the first call to stop
|
||||||
|
p.stopped = true
|
||||||
close(p.queue)
|
close(p.queue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *printer) HandleEvent(event api.ContainerEvent) {
|
func (p *printer) HandleEvent(event api.ContainerEvent) {
|
||||||
// prevent deadlocking, if the printer is done, there's no reader for
|
p.Lock()
|
||||||
// queue, so this write could block indefinitely
|
defer p.Unlock()
|
||||||
if p.stopped.Load() {
|
if p.stopped {
|
||||||
|
// prevent deadlocking, if the printer is done, there's no reader for
|
||||||
|
// queue, so this write could block indefinitely
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.queue <- event
|
p.queue <- event
|
||||||
|
Loading…
x
Reference in New Issue
Block a user