浏览代码

lib/model: Do folder watch operations under lock (fixes #5392) (#5395)

Simon Frei 7 年之前
父节点
当前提交
fc81e2b3d7
共有 1 个文件被更改,包括 12 次插入8 次删除
  1. 12 8
      lib/model/folder.go

+ 12 - 8
lib/model/folder.go

@@ -58,7 +58,7 @@ type folder struct {
 	watchChan        chan []string
 	watchChan        chan []string
 	restartWatchChan chan struct{}
 	restartWatchChan chan struct{}
 	watchErr         error
 	watchErr         error
-	watchErrMut      sync.Mutex
+	watchMut         sync.Mutex
 
 
 	puller puller
 	puller puller
 }
 }
@@ -96,7 +96,7 @@ func newFolder(model *Model, cfg config.FolderConfiguration) folder {
 
 
 		watchCancel:      func() {},
 		watchCancel:      func() {},
 		restartWatchChan: make(chan struct{}, 1),
 		restartWatchChan: make(chan struct{}, 1),
-		watchErrMut:      sync.NewMutex(),
+		watchMut:         sync.NewMutex(),
 	}
 	}
 }
 }
 
 
@@ -550,18 +550,18 @@ func (f *folder) scanTimerFired() {
 }
 }
 
 
 func (f *folder) WatchError() error {
 func (f *folder) WatchError() error {
-	f.watchErrMut.Lock()
-	defer f.watchErrMut.Unlock()
+	f.watchMut.Lock()
+	defer f.watchMut.Unlock()
 	return f.watchErr
 	return f.watchErr
 }
 }
 
 
 // stopWatch immediately aborts watching and may be called asynchronously
 // stopWatch immediately aborts watching and may be called asynchronously
 func (f *folder) stopWatch() {
 func (f *folder) stopWatch() {
+	f.watchMut.Lock()
 	f.watchCancel()
 	f.watchCancel()
-	f.watchErrMut.Lock()
 	prevErr := f.watchErr
 	prevErr := f.watchErr
 	f.watchErr = errWatchNotStarted
 	f.watchErr = errWatchNotStarted
-	f.watchErrMut.Unlock()
+	f.watchMut.Unlock()
 	if prevErr != errWatchNotStarted {
 	if prevErr != errWatchNotStarted {
 		data := map[string]interface{}{
 		data := map[string]interface{}{
 			"folder": f.ID,
 			"folder": f.ID,
@@ -601,8 +601,10 @@ func (f *folder) startWatch() {
 	f.model.fmut.RLock()
 	f.model.fmut.RLock()
 	ignores := f.model.folderIgnores[f.folderID]
 	ignores := f.model.folderIgnores[f.folderID]
 	f.model.fmut.RUnlock()
 	f.model.fmut.RUnlock()
+	f.watchMut.Lock()
 	f.watchChan = make(chan []string)
 	f.watchChan = make(chan []string)
 	f.watchCancel = cancel
 	f.watchCancel = cancel
+	f.watchMut.Unlock()
 	go f.startWatchAsync(ctx, ignores)
 	go f.startWatchAsync(ctx, ignores)
 }
 }
 
 
@@ -614,10 +616,10 @@ func (f *folder) startWatchAsync(ctx context.Context, ignores *ignore.Matcher) {
 		select {
 		select {
 		case <-timer.C:
 		case <-timer.C:
 			eventChan, err := f.Filesystem().Watch(".", ignores, ctx, f.IgnorePerms)
 			eventChan, err := f.Filesystem().Watch(".", ignores, ctx, f.IgnorePerms)
-			f.watchErrMut.Lock()
+			f.watchMut.Lock()
 			prevErr := f.watchErr
 			prevErr := f.watchErr
 			f.watchErr = err
 			f.watchErr = err
-			f.watchErrMut.Unlock()
+			f.watchMut.Unlock()
 			if err != prevErr {
 			if err != prevErr {
 				data := map[string]interface{}{
 				data := map[string]interface{}{
 					"folder": f.ID,
 					"folder": f.ID,
@@ -639,6 +641,8 @@ func (f *folder) startWatchAsync(ctx context.Context, ignores *ignore.Matcher) {
 				timer.Reset(time.Minute)
 				timer.Reset(time.Minute)
 				continue
 				continue
 			}
 			}
+			f.watchMut.Lock()
+			defer f.watchMut.Unlock()
 			watchaggregator.Aggregate(eventChan, f.watchChan, f.FolderConfiguration, f.model.cfg, ctx)
 			watchaggregator.Aggregate(eventChan, f.watchChan, f.FolderConfiguration, f.model.cfg, ctx)
 			l.Debugln("Started filesystem watcher for folder", f.Description())
 			l.Debugln("Started filesystem watcher for folder", f.Description())
 			return
 			return