Skip to content

Commit 9cc9ca7

Browse files
snajpae2b-bot[bot]
authored andcommitted
fix(orchestrator): avoid rootfs startup deadlock
GitOrigin-RevId: e4aaae055e7f475ea4c26340ce68634ef7c39d0b
1 parent 7ecd661 commit 9cc9ca7

3 files changed

Lines changed: 360 additions & 41 deletions

File tree

‎packages/orchestrator/pkg/sandbox/cleanup.go‎

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"slices"
1111
"sync"
1212
"sync/atomic"
13+
"time"
1314

1415
"go.uber.org/zap"
1516

@@ -28,6 +29,25 @@ type Cleanup struct {
2829
mu sync.Mutex
2930
}
3031

32+
const lateCleanupLogMessage = "cleanup callback ran after cleanup completed"
33+
34+
func runLateCleanup(ctx context.Context, f func(context.Context) error, priority bool) {
35+
runCtx := context.WithoutCancel(ctx)
36+
start := time.Now()
37+
err := f(runCtx)
38+
fields := []zap.Field{
39+
zap.Bool("priority", priority),
40+
zap.Duration("duration", time.Since(start)),
41+
}
42+
if err != nil {
43+
logger.L().Error(runCtx, lateCleanupLogMessage, append(fields, zap.Error(err))...)
44+
45+
return
46+
}
47+
48+
logger.L().Info(runCtx, lateCleanupLogMessage, fields...)
49+
}
50+
3151
func NewCleanup() *Cleanup {
3252
return &Cleanup{}
3353
}
@@ -37,35 +57,32 @@ func (c *Cleanup) AddNoContext(ctx context.Context, f func() error) {
3757
}
3858

3959
func (c *Cleanup) Add(ctx context.Context, f func(ctx context.Context) error) {
40-
if c.hasRun.Load() == true {
41-
err := f(context.WithoutCancel(ctx))
42-
if err != nil {
43-
logger.L().Error(ctx, "failed to run function after cleanup has run", zap.Error(err))
44-
}
60+
// Keep the state check and registration under the same lock as Run. Without
61+
// this, Add can observe false, lose the lock to Run, then append after Run has
62+
// already drained the list.
63+
c.mu.Lock()
64+
if !c.hasRun.Load() {
65+
c.cleanup = append(c.cleanup, f)
66+
c.mu.Unlock()
4567

4668
return
4769
}
70+
c.mu.Unlock()
4871

49-
c.mu.Lock()
50-
defer c.mu.Unlock()
51-
52-
c.cleanup = append(c.cleanup, f)
72+
runLateCleanup(ctx, f, false)
5373
}
5474

5575
func (c *Cleanup) AddPriority(ctx context.Context, f func(ctx context.Context) error) {
56-
if c.hasRun.Load() == true {
57-
err := f(context.WithoutCancel(ctx))
58-
if err != nil {
59-
logger.L().Error(ctx, "failed to run priority function after cleanup has run", zap.Error(err))
60-
}
76+
c.mu.Lock()
77+
if !c.hasRun.Load() {
78+
c.priorityCleanup = append(c.priorityCleanup, f)
79+
c.mu.Unlock()
6180

6281
return
6382
}
83+
c.mu.Unlock()
6484

65-
c.mu.Lock()
66-
defer c.mu.Unlock()
67-
68-
c.priorityCleanup = append(c.priorityCleanup, f)
85+
runLateCleanup(ctx, f, true)
6986
}
7087

7188
func (c *Cleanup) Run(ctx context.Context) error {
@@ -80,19 +97,21 @@ func (c *Cleanup) run(ctx context.Context) {
8097
c.hasRun.Store(true)
8198

8299
c.mu.Lock()
83-
defer c.mu.Unlock()
100+
priorityCleanup := c.priorityCleanup
101+
normalCleanup := c.cleanup
102+
c.mu.Unlock()
84103

85104
var errs []error
86105

87-
for _, cleanup := range slices.Backward(c.priorityCleanup) {
88-
err := cleanup(ctx)
106+
for _, f := range slices.Backward(priorityCleanup) {
107+
err := f(ctx)
89108
if err != nil {
90109
errs = append(errs, err)
91110
}
92111
}
93112

94-
for _, cleanup := range slices.Backward(c.cleanup) {
95-
err := cleanup(ctx)
113+
for _, f := range slices.Backward(normalCleanup) {
114+
err := f(ctx)
96115
if err != nil {
97116
errs = append(errs, err)
98117
}

0 commit comments

Comments
 (0)