mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-30 00:40:44 +01:00
fix: prevent stack overflow in ECBalanceTask.reportProgress (#8949)
* fix: prevent stack overflow in ECBalanceTask.reportProgress Add re-entry guard to reportProgress() to prevent infinite recursion. The progressCallback invoked by ReportProgressWithStage can re-enter reportProgress, causing a stack overflow that crashes the worker process (goroutine stack exceeds 1GB limit after ~22M frames). * fix: use atomics for progress and re-entry guard to avoid data races Address review feedback: GetProgress() can be called from a different goroutine while reportProgress is updating the value. Use atomic operations for both the progress field (via Float64bits/Float64frombits) and the reporting re-entry guard (via CompareAndSwap).
This commit is contained in:
1 parent
83a632669a
commit
b0a4647d87
1 file changed
+10
-3
@@ -3,6 +3,8 @@ package ec_balance
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
@@ -22,7 +24,8 @@ type ECBalanceTask struct {
|
||||
volumeID uint32
|
||||
collection string
|
||||
grpcDialOption grpc.DialOption
|
||||
progress float64
|
||||
progress uint64 // atomic; stores float64 bits via math.Float64bits
|
||||
reporting int32 // atomic; re-entry guard to prevent recursive reportProgress calls
|
||||
}
|
||||
|
||||
// NewECBalanceTask creates a new EC balance task instance
|
||||
@@ -206,12 +209,16 @@ func (t *ECBalanceTask) EstimateTime(params *worker_pb.TaskParams) time.Duration
|
||||
|
||||
// GetProgress returns current progress
|
||||
func (t *ECBalanceTask) GetProgress() float64 {
|
||||
return t.progress
|
||||
return math.Float64frombits(atomic.LoadUint64(&t.progress))
|
||||
}
|
||||
|
||||
// reportProgress updates the stored progress and reports it via the callback
|
||||
func (t *ECBalanceTask) reportProgress(progress float64, stage string) {
|
||||
t.progress = progress
|
||||
if !atomic.CompareAndSwapInt32(&t.reporting, 0, 1) {
|
||||
return
|
||||
}
|
||||
defer atomic.StoreInt32(&t.reporting, 0)
|
||||
atomic.StoreUint64(&t.progress, math.Float64bits(progress))
|
||||
t.ReportProgressWithStage(progress, stage)
|
||||
glog.Infof("EC balance volume %d: [%.2f] %s", t.volumeID, progress, stage)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user