diff --git a/lib/model/model.go b/lib/model/model.go index 4cc94238c..878ef9d73 100644 --- a/lib/model/model.go +++ b/lib/model/model.go @@ -465,7 +465,7 @@ func (m *model) warnAboutOverwritingProtectedFiles(cfg config.FolderConfiguratio func (m *model) removeFolder(cfg config.FolderConfiguration) { m.fmut.RLock() - wait := m.folderRunners.RemoveAndWaitChan(cfg.ID, 0) + wait := m.folderRunners.StopAndWaitChan(cfg.ID, 0) m.fmut.RUnlock() <-wait @@ -507,6 +507,7 @@ func (m *model) removeFolder(cfg config.FolderConfiguration) { // Need to hold lock on m.fmut when calling this. func (m *model) cleanupFolderLocked(cfg config.FolderConfiguration) { // clear up our config maps + m.folderRunners.Remove(cfg.ID) delete(m.folderCfgs, cfg.ID) delete(m.folderFiles, cfg.ID) delete(m.folderIgnores, cfg.ID) @@ -536,7 +537,7 @@ func (m *model) restartFolder(from, to config.FolderConfiguration, cacheIgnoredF defer restartMut.Unlock() m.fmut.RLock() - wait := m.folderRunners.RemoveAndWaitChan(from.ID, 0) + wait := m.folderRunners.StopAndWaitChan(from.ID, 0) m.fmut.RUnlock() <-wait diff --git a/lib/model/service_map.go b/lib/model/service_map.go index 988ad520a..0eed99cfc 100644 --- a/lib/model/service_map.go +++ b/lib/model/service_map.go @@ -59,6 +59,34 @@ func (s *serviceMap[K, S]) Get(k K) (v S, ok bool) { return } +// Stop removes the service at the given key from the supervisor, stopping it. +// The service itself is still retained, i.e. a call to Get with the same key +// will still return a result. +func (s *serviceMap[K, S]) Stop(k K) { + if tok, ok := s.tokens[k]; ok { + s.supervisor.Remove(tok) + } + return +} + +// StopAndWaitChan removes the service at the given key from the supervisor, +// stopping it. The service itself is still retained, i.e. a call to Get with +// the same key will still return a result. +// The returned channel will produce precisely one error value: either the +// return value from RemoveAndWait (possibly nil), or errSvcNotFound if the +// service was not found. +func (s *serviceMap[K, S]) StopAndWaitChan(k K, timeout time.Duration) <-chan error { + ret := make(chan error, 1) + if tok, ok := s.tokens[k]; ok { + go func() { + ret <- s.supervisor.RemoveAndWait(tok, timeout) + }() + } else { + ret <- errSvcNotFound + } + return ret +} + // Remove removes the service at the given key, stopping it on the supervisor. // If there is no service at the given key, nothing happens. The return value // indicates whether a service was removed. @@ -66,6 +94,8 @@ func (s *serviceMap[K, S]) Remove(k K) (found bool) { if tok, ok := s.tokens[k]; ok { found = true s.supervisor.Remove(tok) + } else { + _, found = s.services[k] } delete(s.services, k) delete(s.tokens, k) @@ -84,16 +114,8 @@ func (s *serviceMap[K, S]) RemoveAndWait(k K, timeout time.Duration) error { // value: either the return value from RemoveAndWait (possibly nil), or // errSvcNotFound if the service was not found. func (s *serviceMap[K, S]) RemoveAndWaitChan(k K, timeout time.Duration) <-chan error { - ret := make(chan error, 1) - if tok, ok := s.tokens[k]; ok { - go func() { - ret <- s.supervisor.RemoveAndWait(tok, timeout) - }() - } else { - ret <- errSvcNotFound - } + ret := s.StopAndWaitChan(k, timeout) delete(s.services, k) - delete(s.tokens, k) return ret }