Преглед изворни кода

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 <[email protected]>
horus пре 1 година
родитељ
комит
1baa4f4489
1 измењених фајлова са 12 додато и 6 уклоњено
  1. 12 6
      pkg/compose/printer.go

+ 12 - 6
pkg/compose/printer.go

@@ -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