chore(scanner): avoid scan failures and report if they happen (#9888)

This commit is contained in:
Simon Frei
2024-12-28 17:09:38 +01:00
committed by GitHub
parent 9c449c966b
commit 1d2c53bf3c
2 changed files with 34 additions and 13 deletions

View File

@@ -238,17 +238,25 @@ func (w *walker) walkWithoutHashing(ctx context.Context) chan ScanResult {
return finishedChan
}
const walkFailureEventDesc = "Unexpected error while walking the filesystem during scan"
func (w *walker) scan(ctx context.Context, toHashChan chan<- protocol.FileInfo, finishedChan chan<- ScanResult) {
hashFiles := w.walkAndHashFiles(ctx, toHashChan, finishedChan)
if len(w.Subs) == 0 {
w.Filesystem.Walk(".", hashFiles)
if err := w.Filesystem.Walk(".", hashFiles); err != nil {
w.EventLogger.Log(events.Failure, walkFailureEventDesc)
l.Warnf("Aborted scan due to an unexpected error: %v", err)
}
} else {
for _, sub := range w.Subs {
if err := osutil.TraversesSymlink(w.Filesystem, filepath.Dir(sub)); err != nil {
l.Debugf("%v: Skip walking %v as it is below a symlink", w, sub)
continue
}
w.Filesystem.Walk(sub, hashFiles)
if err := w.Filesystem.Walk(sub, hashFiles); err != nil {
w.EventLogger.Log(events.Failure, walkFailureEventDesc)
l.Warnf("Aborted scan of path '%v' due to an unexpected error: %v", sub, err)
}
}
}
close(toHashChan)
@@ -341,7 +349,11 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
if ignoredParent == "" {
// parent isn't ignored, nothing special
return w.handleItem(ctx, path, info, toHashChan, finishedChan)
if err := w.handleItem(ctx, path, info, toHashChan, finishedChan); err != nil {
handleError(ctx, "scan", path, err, finishedChan)
return skip
}
return nil
}
// Part of current path below the ignored (potential) parent
@@ -350,7 +362,11 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
// ignored path isn't actually a parent of the current path
if rel == path {
ignoredParent = ""
return w.handleItem(ctx, path, info, toHashChan, finishedChan)
if err := w.handleItem(ctx, path, info, toHashChan, finishedChan); err != nil {
handleError(ctx, "scan", path, err, finishedChan)
return skip
}
return nil
}
// The previously ignored parent directories of the current, not
@@ -366,7 +382,8 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
return skip
}
if err = w.handleItem(ctx, ignoredParent, info, toHashChan, finishedChan); err != nil {
return err
handleError(ctx, "scan", path, err, finishedChan)
return skip
}
}
ignoredParent = ""
@@ -375,6 +392,9 @@ func (w *walker) walkAndHashFiles(ctx context.Context, toHashChan chan<- protoco
}
}
// Returning an error does not indicate that the walk should be aborted - it
// will simply report the error for that path to the user (same for walk...
// functions called from here).
func (w *walker) handleItem(ctx context.Context, path string, info fs.FileInfo, toHashChan chan<- protocol.FileInfo, finishedChan chan<- ScanResult) error {
switch {
case info.IsSymlink():
@@ -394,8 +414,7 @@ func (w *walker) handleItem(ctx context.Context, path string, info fs.FileInfo,
return w.walkRegular(ctx, path, info, toHashChan)
default:
// A special file, socket, fifo, etc. -- do nothing but return
// success so we continue the walk.
// A special file, socket, fifo, etc. -- do nothing, just skip and continue scanning.
l.Debugf("Skipping non-regular file %s (%s)", path, info.Mode())
return nil
}
@@ -512,8 +531,6 @@ func (w *walker) walkDir(ctx context.Context, relPath string, info fs.FileInfo,
return nil
}
// walkSymlink returns nil or an error, if the error is of the nature that
// it should stop the entire walk.
func (w *walker) walkSymlink(ctx context.Context, relPath string, info fs.FileInfo, finishedChan chan<- ScanResult) error {
// Symlinks are not supported on Windows. We ignore instead of returning
// an error.
@@ -523,8 +540,7 @@ func (w *walker) walkSymlink(ctx context.Context, relPath string, info fs.FileIn
f, err := CreateFileInfo(info, relPath, w.Filesystem, w.ScanOwnership, w.ScanXattrs, w.XattrFilter)
if err != nil {
handleError(ctx, "reading link", relPath, err, finishedChan)
return nil
return err
}
curFile, hasCurFile := w.CurrentFiler.CurrentFile(relPath)
@@ -637,6 +653,7 @@ func (w *walker) updateFileInfo(dst, src protocol.FileInfo) protocol.FileInfo {
}
func handleError(ctx context.Context, context, path string, err error, finishedChan chan<- ScanResult) {
l.Debugf("handle error on '%v': %v: %v", path, context, err)
select {
case finishedChan <- ScanResult{
Err: fmt.Errorf("%s: %w", context, err),

View File

@@ -239,8 +239,12 @@ func TestNormalization(t *testing.T) {
if fd, err := testFs.OpenFile(filepath.Join("normalization", s1, s2), os.O_CREATE|os.O_EXCL, 0o644); err != nil {
t.Fatal(err)
} else {
fd.Write([]byte("test"))
fd.Close()
if _, err := fd.Write([]byte("test")); err != nil {
t.Fatal(err)
}
if err := fd.Close(); err != nil {
t.Fatal(err)
}
}
}
}