diff --git a/store/posixage/internal/flock/flock.go b/store/posixage/internal/flock/flock.go index 19c24403..db995610 100644 --- a/store/posixage/internal/flock/flock.go +++ b/store/posixage/internal/flock/flock.go @@ -77,20 +77,21 @@ func tryLock(ctx context.Context, root *os.Root, exclusive bool) (UnlockFunc, er } err = errors.Join(ErrLockUnsuccessful, err) - if ctx.Err() == nil { - if recoverErr := recoverStaleLock(root, fl); recoverErr != nil && !errors.Is(recoverErr, errRecoverLock) { - return nil, errors.Join(err, recoverErr) - } - fl = nil + if ctx.Err() != nil { + return nil, errors.Join(err, ctx.Err()) + } - fl, err = openFile(root) - if err != nil { - return nil, err - } + // recoverStaleLock always closes fl; clear our reference so the deferred + // close-on-error cleanup does not double-close it. + recoverErr := recoverStaleLock(root, fl) + fl = nil + if recoverErr != nil && !errors.Is(recoverErr, errRecoverLock) { + return nil, errors.Join(err, recoverErr) } - if ctx.Err() != nil { - return nil, errors.Join(err, ctx.Err()) + fl, err = openFile(root) + if err != nil { + return nil, err } err = retryLock(ctx, fl, exclusive) diff --git a/store/posixage/internal/flock/flock_test.go b/store/posixage/internal/flock/flock_test.go index 66239315..789e8252 100644 --- a/store/posixage/internal/flock/flock_test.go +++ b/store/posixage/internal/flock/flock_test.go @@ -122,7 +122,7 @@ func TestFlock(t *testing.T) { require.NoError(t, unlock()) }) - t.Run("caller context can wait past former default timeout", func(t *testing.T) { + t.Run("acquires lock when holder releases before ctx deadline", func(t *testing.T) { root, err := os.OpenRoot(t.TempDir()) require.NoError(t, err) t.Cleanup(func() {