Skip to content

Commit 080fd84

Browse files
committed
fix: wcow: fix race condition in localmounter
> WIP: still ongoing with investigation to determine > exactly which process is accessing the file, will > update on the issue #5807 thread for the records. Fix the race condition with maximum 2 retries. From several tests, 1 retry seems to be enough, even without backoff. Added a simple linear backoff for each retry starting at 30 ms. fixes #5807 Signed-off-by: Anthony Nandaa <profnandaa@gmail.com>
1 parent 648ec56 commit 080fd84

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

snapshot/localmounter_windows.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package snapshot
22

33
import (
44
"os"
5+
"strings"
6+
"time"
57

68
"github.com/Microsoft/go-winio/pkg/bindfilter"
79
"github.com/containerd/containerd/v2/core/mount"
@@ -46,18 +48,51 @@ func (lm *localMounter) Mount() (string, error) {
4648
// The Windows snapshotter does not have any notion of bind mounts. We emulate
4749
// bind mounts here using the bind filter.
4850
if err := bindfilter.ApplyFileBinding(dir, m.Source, m.ReadOnly()); err != nil {
49-
return "", errors.Wrapf(err, "failed to mount %v: %+v", m, err)
51+
return "", errors.Wrapf(err, "failed to mount %v", m)
5052
}
5153
} else {
5254
if err := m.Mount(dir); err != nil {
53-
return "", errors.Wrapf(err, "failed to mount %v: %+v", m, err)
55+
if strings.Contains(
56+
err.Error(),
57+
"cannot access the file because it is being used by another process",
58+
) {
59+
// see https://github.com/moby/buildkit/issues/5807
60+
// if it's a race condition issue, do max 2 retries with some small backoff
61+
// should adjust the retries if this persists but 1 retry
62+
// seems to be enough.
63+
if err := mountWithRetries(m, dir, 2); err != nil {
64+
return "", errors.Wrapf(err, "failed to mount %v", m)
65+
}
66+
} else {
67+
return "", errors.Wrapf(err, "failed to mount (with retries) %v", m)
68+
}
5469
}
5570
}
5671

5772
lm.target = dir
5873
return lm.target, nil
5974
}
6075

76+
func mountWithRetries(m mount.Mount, dir string, retries int) error {
77+
errStr := "cannot access the file because it is being used by another process"
78+
backoff := 30 * time.Millisecond
79+
var err error
80+
81+
for i := range retries {
82+
err = m.Mount(dir)
83+
if err == nil {
84+
return nil
85+
}
86+
if strings.Contains(err.Error(), errStr) {
87+
time.Sleep(time.Duration(i+1) * backoff)
88+
continue
89+
}
90+
return err
91+
}
92+
93+
return err
94+
}
95+
6196
func (lm *localMounter) Unmount() error {
6297
lm.mu.Lock()
6398
defer lm.mu.Unlock()

0 commit comments

Comments
 (0)