fix windows locking

Don't create a new windows handle for the lock.
This commit is contained in:
James Bardin 2017-02-17 10:53:24 -05:00
parent c0dda6a7b3
commit a4283d23f6
2 changed files with 7 additions and 45 deletions

View File

@ -147,6 +147,10 @@ func (s *LocalState) Lock(info *LockInfo) (string, error) {
} }
} }
if s.lockID != "" {
return "", fmt.Errorf("state %q already locked", s.stateFileOut.Name())
}
if err := s.lock(); err != nil { if err := s.lock(); err != nil {
info, infoErr := s.lockInfo() info, infoErr := s.lockInfo()
if infoErr != nil { if infoErr != nil {

View File

@ -4,23 +4,14 @@ package state
import ( import (
"math" "math"
"os"
"sync"
"syscall" "syscall"
"unsafe" "unsafe"
) )
type stateLock struct {
handle syscall.Handle
}
var ( var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll") modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procLockFileEx = modkernel32.NewProc("LockFileEx") procLockFileEx = modkernel32.NewProc("LockFileEx")
procCreateEventW = modkernel32.NewProc("CreateEventW") procCreateEventW = modkernel32.NewProc("CreateEventW")
lockedFilesMu sync.Mutex
lockedFiles = map[*os.File]syscall.Handle{}
) )
const ( const (
@ -31,31 +22,6 @@ const (
) )
func (s *LocalState) lock() error { func (s *LocalState) lock() error {
lockedFilesMu.Lock()
defer lockedFilesMu.Unlock()
name, err := syscall.UTF16PtrFromString(s.PathOut)
if err != nil {
return err
}
handle, err := syscall.CreateFile(
name,
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
// since this file is already open in out process, we need shared
// access here for this call.
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
nil,
syscall.OPEN_EXISTING,
syscall.FILE_ATTRIBUTE_NORMAL,
0,
)
if err != nil {
return err
}
lockedFiles[s.stateFileOut] = handle
// even though we're failing immediately, an overlapped event structure is // even though we're failing immediately, an overlapped event structure is
// required // required
ol, err := newOverlapped() ol, err := newOverlapped()
@ -65,7 +31,7 @@ func (s *LocalState) lock() error {
defer syscall.CloseHandle(ol.HEvent) defer syscall.CloseHandle(ol.HEvent)
return lockFileEx( return lockFileEx(
handle, syscall.Handle(s.stateFileOut.Fd()),
_LOCKFILE_EXCLUSIVE_LOCK|_LOCKFILE_FAIL_IMMEDIATELY, _LOCKFILE_EXCLUSIVE_LOCK|_LOCKFILE_FAIL_IMMEDIATELY,
0, // reserved 0, // reserved
0, // bytes low 0, // bytes low
@ -75,16 +41,8 @@ func (s *LocalState) lock() error {
} }
func (s *LocalState) unlock() error { func (s *LocalState) unlock() error {
lockedFilesMu.Lock() // the file is closed in Unlock
defer lockedFilesMu.Unlock() return nil
handle, ok := lockedFiles[s.stateFileOut]
if !ok {
// we allow multiple Unlock calls
return nil
}
delete(lockedFiles, s.stateFileOut)
return syscall.Close(handle)
} }
func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {