mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Fix potential BSD locking race. (#98)
This commit is contained in:
@@ -51,6 +51,7 @@ const (
|
||||
_IOERR_BEGIN_ATOMIC _ErrorCode = util.IOERR_BEGIN_ATOMIC
|
||||
_IOERR_COMMIT_ATOMIC _ErrorCode = util.IOERR_COMMIT_ATOMIC
|
||||
_IOERR_ROLLBACK_ATOMIC _ErrorCode = util.IOERR_ROLLBACK_ATOMIC
|
||||
_BUSY_SNAPSHOT _ErrorCode = util.BUSY_SNAPSHOT
|
||||
_CANTOPEN_FULLPATH _ErrorCode = util.CANTOPEN_FULLPATH
|
||||
_CANTOPEN_ISDIR _ErrorCode = util.CANTOPEN_ISDIR
|
||||
_READONLY_CANTINIT _ErrorCode = util.READONLY_CANTINIT
|
||||
|
||||
@@ -29,5 +29,12 @@ func osReadLock(file *os.File, _ /*start*/, _ /*len*/ int64, _ /*timeout*/ time.
|
||||
}
|
||||
|
||||
func osWriteLock(file *os.File, _ /*start*/, _ /*len*/ int64, _ /*timeout*/ time.Duration) _ErrorCode {
|
||||
return osLock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
|
||||
rc := osLock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
|
||||
if rc == _BUSY {
|
||||
// The documentation states the lock is upgraded by releasing the previous lock,
|
||||
// then acquiring the new lock.
|
||||
// This is a race, so return BUSY_SNAPSHOT to ensure the transaction is aborted.
|
||||
return _BUSY_SNAPSHOT
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func osDowngradeLock(file *os.File, state LockLevel) _ErrorCode {
|
||||
// In theory, the downgrade to a SHARED cannot fail because another
|
||||
// process is holding an incompatible lock. If it does, this
|
||||
// indicates that the other process is not following the locking
|
||||
// protocol. If this happens, return _IOERR_RDLOCK. Returning
|
||||
// protocol. If this happens, return IOERR_RDLOCK. Returning
|
||||
// BUSY would confuse the upper layer.
|
||||
return _IOERR_RDLOCK
|
||||
}
|
||||
|
||||
@@ -128,10 +128,11 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) {
|
||||
}
|
||||
|
||||
// Lock and truncate the file, if not readonly.
|
||||
// The lock is only released by closing the file.
|
||||
if s.readOnly {
|
||||
rc = _READONLY_CANTINIT
|
||||
} else {
|
||||
if rc := osWriteLock(f, 0, 0, 0); rc != _OK {
|
||||
if rc := osLock(f, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK); rc != _OK {
|
||||
return rc
|
||||
}
|
||||
if err := f.Truncate(0); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user