diff --git a/fs/cache/cache.go b/fs/cache/cache.go index e86bd0ec8..7e1bf2d32 100644 --- a/fs/cache/cache.go +++ b/fs/cache/cache.go @@ -7,6 +7,7 @@ import ( "sync" "github.com/rclone/rclone/fs" + "github.com/rclone/rclone/fs/filter" "github.com/rclone/rclone/lib/cache" ) @@ -101,7 +102,14 @@ func Unpin(f fs.Fs) { // Get gets an fs.Fs named fsString either from the cache or creates it afresh func Get(ctx context.Context, fsString string) (f fs.Fs, err error) { - return GetFn(ctx, fsString, fs.NewFs) + // If we are making a long lived backend which lives longer + // than this request, we want to disconnect it from the + // current context and in particular any WithCancel contexts, + // but we want to preserve the config embedded in the context. + newCtx := context.Background() + newCtx = fs.CopyConfig(newCtx, ctx) + newCtx = filter.CopyConfig(newCtx, ctx) + return GetFn(newCtx, fsString, fs.NewFs) } // GetArr gets []fs.Fs from []fsStrings either from the cache or creates it afresh diff --git a/fs/config.go b/fs/config.go index 939cfd660..a33c4cc1f 100644 --- a/fs/config.go +++ b/fs/config.go @@ -189,6 +189,19 @@ func GetConfig(ctx context.Context) *ConfigInfo { return c.(*ConfigInfo) } +// CopyConfig copies the global config (if any) from srcCtx into +// dstCtx returning the new context. +func CopyConfig(dstCtx, srcCtx context.Context) context.Context { + if srcCtx == nil { + return dstCtx + } + c := srcCtx.Value(configContextKey) + if c == nil { + return dstCtx + } + return context.WithValue(dstCtx, configContextKey, c) +} + // AddConfig returns a mutable config structure based on a shallow // copy of that found in ctx and returns a new context with that added // to it. diff --git a/fs/filter/filter.go b/fs/filter/filter.go index 304ab87f8..7e38aa8bc 100644 --- a/fs/filter/filter.go +++ b/fs/filter/filter.go @@ -615,6 +615,19 @@ func GetConfig(ctx context.Context) *Filter { return c.(*Filter) } +// CopyConfig copies the global config (if any) from srcCtx into +// dstCtx returning the new context. +func CopyConfig(dstCtx, srcCtx context.Context) context.Context { + if srcCtx == nil { + return dstCtx + } + c := srcCtx.Value(configContextKey) + if c == nil { + return dstCtx + } + return context.WithValue(dstCtx, configContextKey, c) +} + // AddConfig returns a mutable config structure based on a shallow // copy of that found in ctx and returns a new context with that added // to it.