mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-19 21:10:48 +02:00
Stop the filer test helpers from pinning gigabytes of log buffers (#10560)
* log buffer: wake the interval loop on shutdown instead of sleeping through it loopInterval parked in time.Sleep(flushInterval) and only re-checked IsStopping when it woke, so a buffer shut down early kept both loop goroutines - and the PreviousBufferCount+1 slabs of BufferSize they reach - alive for up to a full interval afterwards. Select on shutdownCh against a ticker instead, and give the loops a WaitGroup so a test can observe that they exit. * test: release the filers the server tests build Every helper here left its filer's meta log buffer running, so each test pinned PreviousBufferCount+1 buffers of BufferSize for the rest of the run: ~3.5GB of live heap across the package, which overruns the address space on linux/386 and kills the 32-bit job with an out-of-memory throw. Thread the test through the helpers so the buffer is shut down on cleanup, and shut the subscribe harness's filer down outright - its deletion loop keeps the whole filer reachable otherwise. That harness quiesces its flush path first, since Filer.Shutdown closes the store a flush still in flight would write through.
This commit is contained in:
@@ -193,7 +193,8 @@ type LogBuffer struct {
|
||||
// Notified only when a flush lands, for readers that cannot act on an append
|
||||
flushSubscribers map[string]chan struct{}
|
||||
isStopping *atomic.Bool
|
||||
shutdownCh chan struct{} // closed by ShutdownLogBuffer to wake blocked subscribers
|
||||
shutdownCh chan struct{} // closed by ShutdownLogBuffer to wake blocked subscribers
|
||||
loopsDone sync.WaitGroup // loopFlush and loopInterval signal exit
|
||||
isAllFlushed bool
|
||||
flushChan chan *dataToFlush
|
||||
flushBudget *flushBudget
|
||||
@@ -235,6 +236,7 @@ func NewLogBuffer(name string, flushInterval time.Duration, flushFn LogFlushFunc
|
||||
},
|
||||
}
|
||||
lb.lastFlushedOffset.Store(-1) // Nothing flushed to disk yet
|
||||
lb.loopsDone.Add(2)
|
||||
go lb.loopFlush()
|
||||
go lb.loopInterval()
|
||||
return lb
|
||||
@@ -740,6 +742,7 @@ func (logBuffer *LogBuffer) queueFlush(d *dataToFlush) bool {
|
||||
}
|
||||
|
||||
func (logBuffer *LogBuffer) loopFlush() {
|
||||
defer logBuffer.loopsDone.Done()
|
||||
for d := range logBuffer.flushChan {
|
||||
if d == nil {
|
||||
break // shutdown sentinel
|
||||
@@ -777,10 +780,17 @@ func (logBuffer *LogBuffer) loopFlush() {
|
||||
}
|
||||
|
||||
func (logBuffer *LogBuffer) loopInterval() {
|
||||
for !logBuffer.IsStopping() {
|
||||
time.Sleep(logBuffer.flushInterval)
|
||||
if logBuffer.IsStopping() {
|
||||
defer logBuffer.loopsDone.Done()
|
||||
// Wake on shutdown instead of sleeping through the interval: a goroutine
|
||||
// parked in time.Sleep keeps the buffer and its ~40MB of slabs reachable
|
||||
// for up to flushInterval after ShutdownLogBuffer.
|
||||
ticker := time.NewTicker(logBuffer.flushInterval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-logBuffer.shutdownCh:
|
||||
return
|
||||
case <-ticker.C:
|
||||
}
|
||||
|
||||
logBuffer.Lock()
|
||||
|
||||
Reference in New Issue
Block a user