lock: Always cancel the returned Get(R)Lock context (#12162)

* lock: Always cancel the returned Get(R)Lock context

There is a leak with cancel created inside the locking mechanism. The
cancel purpose was to cancel operations such erasure get/put that are
holding non-refreshable locks.

This PR will ensure the created context.Cancel is passed to the unlock
API so it will cleanup and avoid leaks.

* locks: Avoid returning nil cancel in local lockers

Since there is no Refresh mechanism in the local locking mechanism, we
do not generate a new context or cancel. Currently, a nil cancel
function is returned but this can cause a crash. Return a dummy function
instead.
This commit is contained in:
Anis Elleuch
2021-04-28 00:12:50 +01:00
committed by GitHub
parent fbdfa11f76
commit 9e797532dc
12 changed files with 146 additions and 129 deletions

View File

@@ -92,16 +92,18 @@ func (s *safeDuration) Get() time.Duration {
// The function will block until the context is canceled.
// There should only ever be one scanner running per cluster.
func runDataScanner(ctx context.Context, objAPI ObjectLayer) {
var err error
// Make sure only 1 scanner is running on the cluster.
locker := objAPI.NewNSLock(minioMetaBucket, "runDataScanner.lock")
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for {
ctx, err = locker.GetLock(ctx, dataScannerLeaderLockTimeout)
var err error
var cancel context.CancelFunc
ctx, cancel, err = locker.GetLock(ctx, dataScannerLeaderLockTimeout)
if err != nil {
time.Sleep(time.Duration(r.Float64() * float64(scannerCycle.Get())))
continue
}
defer cancel()
break
// No unlock for "leader" lock.
}