github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/osutils/lockfile/pidlock_win.go (about) 1 //go:build windows 2 // +build windows 3 4 package lockfile 5 6 import ( 7 "os" 8 "syscall" 9 10 "github.com/ActiveState/cli/internal/errs" 11 ) 12 13 // ErrorLockViolation is the error no returned if a lock fails on Windows 14 const ErrorLockViolation syscall.Errno = 0x21 // 33 15 16 // PidExists checks if a process with the given PID exists and is running 17 func PidExists(pid int) bool { 18 _, err := os.FindProcess(int(pid)) 19 return err == nil 20 } 21 22 // LockFile attempts to add a lock to the file f 23 func LockFile(f *os.File) error { 24 _, errNo := lockFileEx(syscall.Handle(f.Fd()), winLockfileExclusiveLock|winLockfileFailImmediately, 0, 1, 0, &syscall.Overlapped{}) 25 26 if errNo > 0 { 27 if errNo == ErrorLockViolation || errNo == syscall.ERROR_IO_PENDING { 28 return errs.New("cannot obtain lock") 29 } 30 31 return errs.New("unknown error: %d", errNo) 32 } 33 return nil 34 } 35 36 // LockRelease releases a file lock 37 func LockRelease(f *os.File) error { 38 // mark the file as unlocked 39 if _, errNo := unlockFileEx(syscall.Handle(f.Fd()), 0, 1, 0, &syscall.Overlapped{}); errNo > 0 { 40 return errs.New("error releasing windows file lock. errno: %d", errNo) 41 } 42 return nil 43 } 44 45 func (pl *PidLock) cleanLockFile(keep bool) error { 46 err := LockRelease(pl.file) 47 if err != nil { 48 return errs.Wrap(err, "failed to release lock on lock file %s", pl.path) 49 } 50 err = pl.file.Close() 51 if err != nil { 52 return errs.Wrap(err, "failed to close lock file %s", pl.path) 53 } 54 // On Windows, we have to remove the file AFTER it is closed. 55 // It is not an error if it fails, because that could mean that another 56 // process has opened a new file handle for the file already. 57 if !keep { 58 _ = os.Remove(pl.path) 59 } 60 return nil 61 }