Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions pkg/lockfile/lockfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,10 +417,12 @@ func (l *LockFile) tryLock(lType rawfilelock.LockType) error {
success = l.rwMutex.TryLock()
rwMutexUnlocker = l.rwMutex.Unlock
}
if !success {
if !success || !l.stateMutex.TryLock() {
if success {
rwMutexUnlocker()
}
return fmt.Errorf("resource temporarily unavailable")
}
l.stateMutex.Lock()
defer l.stateMutex.Unlock()
if l.counter == 0 {
// If we're the first reference on the lock, we need to open the file again.
Expand Down
49 changes: 49 additions & 0 deletions pkg/lockfile/lockfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,55 @@ func TestTryReadLockFile(t *testing.T) {
assert.Nil(t, <-errChan)
}

func TestTryLockState(t *testing.T) {
l, err := getTempLockfile()
require.NoError(t, err, "creating lock")
defer os.Remove(l.name)

// Take a write lock somewhere.
cmd, wc, rc, err := subLock(l)
require.NoError(t, err)
_, err = io.Copy(io.Discard, rc)
require.NoError(t, err)

err = l.TryRLock()
assert.NotNil(t, err)

// Lock and hold state mutex.
locked := make(chan bool)
go func() {
locked <- false
l.RLock()
locked <- true
l.Unlock()
locked <- false
}()

assert.False(t, <-locked)

// Wait state mutex is locked.
for !l.stateMutex.TryLock() {
l.stateMutex.Unlock()
time.Sleep(100 * time.Millisecond)
}

// Try locks should fail without blocking.
errChan := make(chan error)
go func() {
errChan <- l.TryRLock()
errChan <- l.TryLock()
}()
assert.NotNil(t, <-errChan)
assert.NotNil(t, <-errChan)

wc.Close()
err = cmd.Wait()
require.NoError(t, err)

assert.True(t, <-locked)
assert.False(t, <-locked)
}

func TestLockfileRead(t *testing.T) {
l, err := getTempLockfile()
require.Nil(t, err, "error getting temporary lock file")
Expand Down