From d72181c8c1e49d48b7219e105291895b49f1e54a Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 9 Aug 2020 13:54:39 +0200 Subject: [PATCH] Ensure that the lock cleanup handler is run after the global one cleanup handlers run in the order in which they are added. As Go calls init() functions in lexical order, the cleanup handler from global.go was registered before that from lock.go, which is the correct order. Make this order explicit to ensure that this won't break accidentally. --- cmd/restic/global.go | 2 ++ cmd/restic/lock.go | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd/restic/global.go b/cmd/restic/global.go index 9f42f851a..e3b4020d6 100644 --- a/cmd/restic/global.go +++ b/cmd/restic/global.go @@ -98,6 +98,8 @@ func init() { var cancel context.CancelFunc globalOptions.ctx, cancel = context.WithCancel(context.Background()) AddCleanupHandler(func() error { + // Must be called before the unlock cleanup handler to ensure that the latter is + // not blocked due to limited number of backend connections, see #1434 cancel() return nil }) diff --git a/cmd/restic/lock.go b/cmd/restic/lock.go index 822059943..64f82cf52 100644 --- a/cmd/restic/lock.go +++ b/cmd/restic/lock.go @@ -16,6 +16,7 @@ var globalLocks struct { cancelRefresh chan struct{} refreshWG sync.WaitGroup sync.Mutex + sync.Once } func lockRepo(ctx context.Context, repo *repository.Repository) (*restic.Lock, error) { @@ -27,6 +28,12 @@ func lockRepoExclusive(ctx context.Context, repo *repository.Repository) (*resti } func lockRepository(ctx context.Context, repo *repository.Repository, exclusive bool) (*restic.Lock, error) { + // make sure that a repository is unlocked properly and after cancel() was + // called by the cleanup handler in global.go + globalLocks.Do(func() { + AddCleanupHandler(unlockAll) + }) + lockFn := restic.NewLock if exclusive { lockFn = restic.NewExclusiveLock @@ -128,7 +135,3 @@ func unlockAll() error { return nil } - -func init() { - AddCleanupHandler(unlockAll) -}