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) -}