Skip to content

Commit 3719692

Browse files
authored
Fix potential BSD locking race. (#98)
1 parent f7ac770 commit 3719692

File tree

4 files changed

+12
-3
lines changed

4 files changed

+12
-3
lines changed

vfs/const.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const (
5151
_IOERR_BEGIN_ATOMIC _ErrorCode = util.IOERR_BEGIN_ATOMIC
5252
_IOERR_COMMIT_ATOMIC _ErrorCode = util.IOERR_COMMIT_ATOMIC
5353
_IOERR_ROLLBACK_ATOMIC _ErrorCode = util.IOERR_ROLLBACK_ATOMIC
54+
_BUSY_SNAPSHOT _ErrorCode = util.BUSY_SNAPSHOT
5455
_CANTOPEN_FULLPATH _ErrorCode = util.CANTOPEN_FULLPATH
5556
_CANTOPEN_ISDIR _ErrorCode = util.CANTOPEN_ISDIR
5657
_READONLY_CANTINIT _ErrorCode = util.READONLY_CANTINIT

vfs/os_bsd.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,12 @@ func osReadLock(file *os.File, _ /*start*/, _ /*len*/ int64, _ /*timeout*/ time.
2929
}
3030

3131
func osWriteLock(file *os.File, _ /*start*/, _ /*len*/ int64, _ /*timeout*/ time.Duration) _ErrorCode {
32-
return osLock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
32+
rc := osLock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
33+
if rc == _BUSY {
34+
// The documentation states the lock is upgraded by releasing the previous lock,
35+
// then acquiring the new lock.
36+
// This is a race, so return BUSY_SNAPSHOT to ensure the transaction is aborted.
37+
return _BUSY_SNAPSHOT
38+
}
39+
return rc
3340
}

vfs/os_unix_lock.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {
4848
// In theory, the downgrade to a SHARED cannot fail because another
4949
// process is holding an incompatible lock. If it does, this
5050
// indicates that the other process is not following the locking
51-
// protocol. If this happens, return _IOERR_RDLOCK. Returning
51+
// protocol. If this happens, return IOERR_RDLOCK. Returning
5252
// BUSY would confuse the upper layer.
5353
return _IOERR_RDLOCK
5454
}

vfs/shm_bsd.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,11 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) {
128128
}
129129

130130
// Lock and truncate the file, if not readonly.
131+
// The lock is only released by closing the file.
131132
if s.readOnly {
132133
rc = _READONLY_CANTINIT
133134
} else {
134-
if rc := osWriteLock(f, 0, 0, 0); rc != _OK {
135+
if rc := osLock(f, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK); rc != _OK {
135136
return rc
136137
}
137138
if err := f.Truncate(0); err != nil {

0 commit comments

Comments
 (0)