diff --git a/lib/model/folder.go b/lib/model/folder.go index d34fd8ec7..ef921a007 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -37,6 +37,7 @@ type folder struct { scanNow chan rescanRequest scanDelay chan time.Duration initialScanFinished chan struct{} + stopped chan struct{} pullScheduled chan struct{} @@ -81,6 +82,7 @@ func newFolder(model *Model, cfg config.FolderConfiguration) folder { watchCancel: func() {}, watchErr: errWatchNotStarted, watchErrMut: sync.NewMutex(), + stopped: make(chan struct{}), } } @@ -91,6 +93,7 @@ func (f *folder) Serve() { defer func() { f.scanTimer.Stop() f.setState(FolderIdle) + close(f.stopped) }() pause := f.basePause() @@ -223,6 +226,7 @@ func (f *folder) Delay(next time.Duration) { func (f *folder) Stop() { f.cancel() + <-f.stopped } // CheckHealth checks the folder for common errors, updates the folder state diff --git a/lib/model/model.go b/lib/model/model.go index faeae8460..cdaeb13cf 100644 --- a/lib/model/model.go +++ b/lib/model/model.go @@ -344,10 +344,14 @@ func (m *Model) RemoveFolder(cfg config.FolderConfiguration) { } func (m *Model) tearDownFolderLocked(cfg config.FolderConfiguration) { - // Stop the services running for this folder - for _, id := range m.folderRunnerTokens[cfg.ID] { - m.Remove(id) + // Stop the services running for this folder and wait for them to finish + // stopping to prevent races on restart. + tokens := m.folderRunnerTokens[cfg.ID] + m.fmut.Unlock() + for _, id := range tokens { + m.RemoveAndWait(id, 0) } + m.fmut.Lock() // Close connections to affected devices for _, dev := range cfg.Devices {