AI codebase review
fix: duplicate search no longer hangs on files swapped for FIFOs Candidates were reopened by path with os.Open after the scan. A file replaced by a FIFO (or a symlink to one) blocked open(2) forever, and context cancellation could not interrupt it, wedging the duplicate view and --duplicates. Content is now opened with O_NOFOLLOW|O_NONBLOCK on Unix; the existing regular-file check then skips it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1f9429ea74
commit
5966fdd91e
@@ -0,0 +1,51 @@
|
||||
//go:build unix
|
||||
|
||||
package duplicate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/andydixon/mapsize/internal/scan"
|
||||
)
|
||||
|
||||
// A candidate replaced by a FIFO (or a symlink to one) after the scan must
|
||||
// be skipped, not block the search forever in open(2).
|
||||
func TestFindSkipsSwappedFIFO(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
for _, n := range []string{"a", "b", "c"} {
|
||||
os.WriteFile(filepath.Join(root, n), []byte("same"), 0o644)
|
||||
}
|
||||
s, err := scan.Start(context.Background(), root, scan.Options{Workers: 1})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
<-s.Done()
|
||||
os.Remove(filepath.Join(root, "b"))
|
||||
if err := syscall.Mkfifo(filepath.Join(root, "b"), 0o644); err != nil {
|
||||
t.Skip("mkfifo:", err)
|
||||
}
|
||||
fifo2 := filepath.Join(t.TempDir(), "p")
|
||||
syscall.Mkfifo(fifo2, 0o644)
|
||||
os.Remove(filepath.Join(root, "c"))
|
||||
os.Symlink(fifo2, filepath.Join(root, "c"))
|
||||
|
||||
done := make(chan error, 1)
|
||||
var f Finder
|
||||
go func() { _, err := f.Find(context.Background(), s.Tree, Options{}); done <- err }()
|
||||
select {
|
||||
case err := <-done:
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("duplicate search blocked on a FIFO")
|
||||
}
|
||||
if p := f.Progress(); p.Skipped != 2 {
|
||||
t.Fatalf("skipped=%d want 2", p.Skipped)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user