From a64eba668f717ff74cd462b120e96df80c47f692 Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Sun, 13 Oct 2024 18:01:46 +0300 Subject: [PATCH] Fix windows WithDirLock to exclusive lock We use LOCKFILE_FAIL_IMMEDIATELY, creating a shared lock that fail immediately if the lock cannot be acquired. This does not match the behavior of the unix version and does not make sense. Using now LOCKFILE_EXCLUSIVE_LOCK to acquire exclusive lock blocking until the lock can be acquired. Add constants for the flags and add comments for the argument names to prevent future errors. Signed-off-by: Nir Soffer --- pkg/lockutil/lockutil_windows.go | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/pkg/lockutil/lockutil_windows.go b/pkg/lockutil/lockutil_windows.go index 31f31294604..f191559ab51 100644 --- a/pkg/lockutil/lockutil_windows.go +++ b/pkg/lockutil/lockutil_windows.go @@ -33,20 +33,37 @@ var ( procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") ) +const ( + // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx + LOCKFILE_EXCLUSIVE_LOCK = 0x00000002 + LOCKFILE_FAIL_IMMEDIATELY = 0x00000001 +) + func WithDirLock(dir string, fn func() error) error { dirFile, err := os.OpenFile(dir+".lock", os.O_CREATE, 0o644) if err != nil { return err } defer dirFile.Close() - // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx - // 1 lock immediately - if err := lockFileEx(syscall.Handle(dirFile.Fd()), 1, 0, 1, 0, &syscall.Overlapped{}); err != nil { + if err := lockFileEx( + syscall.Handle(dirFile.Fd()), // hFile + LOCKFILE_EXCLUSIVE_LOCK, // dwFlags + 0, // dwReserved + 1, // nNumberOfBytesToLockLow + 0, // nNumberOfBytesToLockHigh + &syscall.Overlapped{}, // lpOverlapped + ); err != nil { return fmt.Errorf("failed to lock %q: %w", dir, err) } defer func() { - if err := unlockFileEx(syscall.Handle(dirFile.Fd()), 0, 1, 0, &syscall.Overlapped{}); err != nil { + if err := unlockFileEx( + syscall.Handle(dirFile.Fd()), // hFile + 0, // dwReserved + 1, // nNumberOfBytesToLockLow + 0, // nNumberOfBytesToLockHigh + &syscall.Overlapped{}, // lpOverlapped + ); err != nil { logrus.WithError(err).Errorf("failed to unlock %q", dir) } }()