diff --git a/flock.go b/flock.go index a2d7a07..725b2ad 100644 --- a/flock.go +++ b/flock.go @@ -185,3 +185,12 @@ func (f *Flock) ensureFhState() { f.fh = nil } + +func (f *Flock) reset() { + f.l = false + f.r = false + + _ = f.fh.Close() + + f.fh = nil +} diff --git a/flock_unix.go b/flock_unix.go index a394c3d..ad30aa3 100644 --- a/flock_unix.go +++ b/flock_unix.go @@ -56,7 +56,8 @@ func (f *Flock) lock(locked *bool, flag int) error { defer f.ensureFhState() } - if err := syscall.Flock(int(f.fh.Fd()), flag); err != nil { + err := syscall.Flock(int(f.fh.Fd()), flag) + if err != nil { shouldRetry, reopenErr := f.reopenFDOnError(err) if reopenErr != nil { return reopenErr @@ -66,7 +67,8 @@ func (f *Flock) lock(locked *bool, flag int) error { return err } - if err = syscall.Flock(int(f.fh.Fd()), flag); err != nil { + err = syscall.Flock(int(f.fh.Fd()), flag) + if err != nil { return err } } @@ -99,15 +101,12 @@ func (f *Flock) Unlock() error { } // Mark the file as unlocked. - if err := syscall.Flock(int(f.fh.Fd()), syscall.LOCK_UN); err != nil { + err := syscall.Flock(int(f.fh.Fd()), syscall.LOCK_UN) + if err != nil { return err } - _ = f.fh.Close() - - f.l = false - f.r = false - f.fh = nil + f.reset() return nil } @@ -167,7 +166,8 @@ retry: } if !retried { - if shouldRetry, reopenErr := f.reopenFDOnError(err); reopenErr != nil { + shouldRetry, reopenErr := f.reopenFDOnError(err) + if reopenErr != nil { return false, reopenErr } else if shouldRetry { retried = true @@ -180,9 +180,8 @@ retry: // reopenFDOnError determines whether we should reopen the file handle in readwrite mode and try again. // This comes from `util-linux/sys-utils/flock.c`: -// -// Since Linux 3.4 (commit 55725513) -// Probably NFSv4 where flock() is emulated by fcntl(). +// > Since Linux 3.4 (commit 55725513) +// > Probably NFSv4 where flock() is emulated by fcntl(). func (f *Flock) reopenFDOnError(err error) (bool, error) { if !errors.Is(err, syscall.EIO) && !errors.Is(err, syscall.EBADF) { return false, nil diff --git a/flock_unix_variants.go b/flock_unix_variants.go index 2cd5f78..4774b01 100644 --- a/flock_unix_variants.go +++ b/flock_unix_variants.go @@ -99,7 +99,8 @@ func (f *Flock) lock(locked *bool, flag lockType) error { defer f.ensureFhState() } - if _, err := f.doLock(waitLock, flag, true); err != nil { + _, err := f.doLock(waitLock, flag, true) + if err != nil { return err } @@ -137,16 +138,19 @@ func (f *Flock) doLock(cmd cmdType, lt lockType, blocking bool) (bool, error) { l := locks[ino] - if l.owner == f { + switch { + case l.owner == f: // This file already owns the lock, but the call may change its lock type. - } else if l.owner == nil { + case l.owner == nil: // No owner: it's ours now. l.owner = f - } else if !blocking { + + case !blocking: // Already owned: cannot take the lock. mu.Unlock() return false, nil - } else { + + default: // Already owned: add a channel to wait on. wait = make(chan *Flock) l.queue = append(l.queue, wait) @@ -188,11 +192,7 @@ func (f *Flock) Unlock() error { return err } - _ = f.fh.Close() - - f.l = false - f.r = false - f.fh = nil + f.reset() return nil } diff --git a/flock_windows.go b/flock_windows.go index eb4dee7..1945d0d 100644 --- a/flock_windows.go +++ b/flock_windows.go @@ -6,6 +6,7 @@ package flock import ( + "errors" "syscall" ) @@ -85,11 +86,7 @@ func (f *Flock) Unlock() error { return errNo } - _ = f.fh.Close() - - f.l = false - f.r = false - f.fh = nil + f.reset() return nil } @@ -137,7 +134,7 @@ func (f *Flock) try(locked *bool, flag uint32) (bool, error) { _, errNo := lockFileEx(syscall.Handle(f.fh.Fd()), flag|winLockfileFailImmediately, 0, 1, 0, &syscall.Overlapped{}) if errNo > 0 { - if errNo == ErrorLockViolation || errNo == syscall.ERROR_IO_PENDING { + if errors.Is(errNo, ErrorLockViolation) || errors.Is(errNo, syscall.ERROR_IO_PENDING) { return false, nil }