From f47893873dc21ddde3d69d5d34c96babf62d2290 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 19 Feb 2021 13:13:54 +0000 Subject: [PATCH] fs: fix failed token refresh on mounts created via the rc Users have noticed that backends created via the rc have been failing to refresh their tokens with this error: Token refresh failed try 1/5: context canceled This is because the rc server cancels the context used to make the backend when the request has finished. This same context is used to refresh the token and the oauth library checks to see if the context has been cancelled. This patch creates a new context for the cached backends and copies the global and filter config into the new context. See: https://forum.rclone.org/t/google-drive-token-refresh-failed/22283 --- fs/cache/cache.go | 10 +++++++++- fs/config.go | 13 +++++++++++++ fs/filter/filter.go | 13 +++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) 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.