瀏覽代碼

watch: fix a segfault on linux (#148)

Nick Santos 7 年之前
父節點
當前提交
3850a34114
共有 2 個文件被更改,包括 52 次插入5 次删除
  1. 33 0
      pkg/watch/notify_test.go
  2. 19 5
      pkg/watch/watcher_linux.go

+ 33 - 0
pkg/watch/notify_test.go

@@ -240,6 +240,39 @@ func TestSingleFile(t *testing.T) {
 	f.assertEvents(path)
 }
 
+func TestWriteBrokenLink(t *testing.T) {
+	f := newNotifyFixture(t)
+	defer f.tearDown()
+
+	link := filepath.Join(f.watched.Path(), "brokenLink")
+	missingFile := filepath.Join(f.watched.Path(), "missingFile")
+	err := os.Symlink(missingFile, link)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	f.assertEvents(link)
+}
+
+func TestWriteGoodLink(t *testing.T) {
+	f := newNotifyFixture(t)
+	defer f.tearDown()
+
+	goodFile := filepath.Join(f.watched.Path(), "goodFile")
+	err := ioutil.WriteFile(goodFile, []byte("hello"), 0644)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	link := filepath.Join(f.watched.Path(), "goodFileSymlink")
+	err = os.Symlink(goodFile, link)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	f.assertEvents(goodFile, link)
+}
+
 type notifyFixture struct {
 	t       *testing.T
 	root    *TempDir

+ 19 - 5
pkg/watch/watcher_linux.go

@@ -79,7 +79,17 @@ func (d *linuxNotify) Errors() chan error {
 
 func (d *linuxNotify) loop() {
 	for e := range d.events {
-		if e.Op&fsnotify.Create == fsnotify.Create && isDir(e.Name) {
+		isCreateOp := e.Op&fsnotify.Create == fsnotify.Create
+		shouldWalk := false
+		if isCreateOp {
+			isDir, err := isDir(e.Name)
+			if err != nil {
+				log.Printf("Error stat-ing file %s: %s", e.Name, err)
+				continue
+			}
+			shouldWalk = isDir
+		}
+		if shouldWalk {
 			err := filepath.Walk(e.Name, func(path string, mode os.FileInfo, err error) error {
 				if err != nil {
 					return err
@@ -140,10 +150,14 @@ func NewWatcher() (*linuxNotify, error) {
 	return wmw, nil
 }
 
-func isDir(pth string) bool {
-	fi, _ := os.Stat(pth)
-
-	return fi.IsDir()
+func isDir(pth string) (bool, error) {
+	fi, err := os.Lstat(pth)
+	if os.IsNotExist(err) {
+		return false, nil
+	} else if err != nil {
+		return false, err
+	}
+	return fi.IsDir(), nil
 }
 
 func checkInotifyLimits() error {