diff --git a/fs/march/march.go b/fs/march/march.go index 981e220fb..7f938b67d 100644 --- a/fs/march/march.go +++ b/fs/march/march.go @@ -146,7 +146,12 @@ func (m *March) Run() { // Now we have traversed this directory, send these // jobs off for traversal in the background for _, newJob := range jobs { - in <- newJob + select { + case <-m.ctx.Done(): + // discard job if finishing + traversing.Done() + case in <- newJob: + } } }() } @@ -164,6 +169,13 @@ func (m *March) Run() { dstRemote: m.dir, dstDepth: dstDepth - 1, } + go func() { + // when the context is cancelled discard the remaining jobs + <-m.ctx.Done() + for range in { + traversing.Done() + } + }() traversing.Wait() close(in) wg.Wait() diff --git a/fs/sync/sync.go b/fs/sync/sync.go index 8febf769d..be7152fd0 100644 --- a/fs/sync/sync.go +++ b/fs/sync/sync.go @@ -224,10 +224,18 @@ func (s *syncCopyMove) pairChecker(in fs.ObjectPairChan, out fs.ObjectPairChan, } else { // If successful zero out the dst as it is no longer there and copy the file pair.Dst = nil - out <- pair + select { + case <-s.ctx.Done(): + return + case out <- pair: + } } } else { - out <- pair + select { + case <-s.ctx.Done(): + return + case out <- pair: + } } } } else { @@ -261,7 +269,11 @@ func (s *syncCopyMove) pairRenamer(in fs.ObjectPairChan, out fs.ObjectPairChan, src := pair.Src if !s.tryRename(src) { // pass on if not renamed - out <- pair + select { + case <-s.ctx.Done(): + return + case out <- pair: + } } case <-s.ctx.Done(): return @@ -407,6 +419,7 @@ func (s *syncCopyMove) deleteFiles(checkSrcMap bool) error { // Delete the spare files toDelete := make(fs.ObjectsChan, fs.Config.Transfers) go func() { + outer: for remote, o := range s.dstFiles { if checkSrcMap { _, exists := s.srcFiles[remote] @@ -417,7 +430,11 @@ func (s *syncCopyMove) deleteFiles(checkSrcMap bool) error { if s.aborting() { break } - toDelete <- o + select { + case <-s.ctx.Done(): + break outer + case toDelete <- o: + } } close(toDelete) }() @@ -612,7 +629,11 @@ func (s *syncCopyMove) run() error { s.makeRenameMap() // Attempt renames for all the files which don't have a matching dst for _, src := range s.renameCheck { - s.toBeRenamed <- fs.ObjectPair{Src: src, Dst: nil} + select { + case <-s.ctx.Done(): + break + case s.toBeRenamed <- fs.ObjectPair{Src: src, Dst: nil}: + } } } @@ -646,6 +667,9 @@ func (s *syncCopyMove) run() error { //delete empty subdirectories that were part of the move s.processError(deleteEmptyDirectories(s.fsrc, s.srcEmptyDirs)) } + + // cancel the context to free resources + s.cancel() return s.currentError() } @@ -663,7 +687,11 @@ func (s *syncCopyMove) DstOnly(dst fs.DirEntry) (recurse bool) { s.dstFiles[x.Remote()] = x s.dstFilesMu.Unlock() case fs.DeleteModeDuring, fs.DeleteModeOnly: - s.deleteFilesCh <- x + select { + case <-s.ctx.Done(): + return + case s.deleteFilesCh <- x: + } default: panic(fmt.Sprintf("unexpected delete mode %d", s.deleteMode)) } @@ -692,10 +720,18 @@ func (s *syncCopyMove) SrcOnly(src fs.DirEntry) (recurse bool) { case fs.Object: if s.trackRenames { // Save object to check for a rename later - s.trackRenamesCh <- x + select { + case <-s.ctx.Done(): + return + case s.trackRenamesCh <- x: + } } else { // No need to check since doesn't exist - s.toBeUploaded <- fs.ObjectPair{Src: x, Dst: nil} + select { + case <-s.ctx.Done(): + return + case s.toBeUploaded <- fs.ObjectPair{Src: x, Dst: nil}: + } } case fs.Directory: // Do the same thing to the entire contents of the directory @@ -719,7 +755,11 @@ func (s *syncCopyMove) Match(dst, src fs.DirEntry) (recurse bool) { } dstX, ok := dst.(fs.Object) if ok { - s.toBeChecked <- fs.ObjectPair{Src: srcX, Dst: dstX} + select { + case <-s.ctx.Done(): + return + case s.toBeChecked <- fs.ObjectPair{Src: srcX, Dst: dstX}: + } } else { // FIXME src is file, dst is directory err := errors.New("can't overwrite directory with file")