diff options
author | 2024-12-17 23:16:20 +0000 | |
---|---|---|
committer | 2024-12-17 23:16:20 +0000 | |
commit | c953f57e55810fa0e3201a67a4622fe4ac39c278 (patch) | |
tree | 6b059966b98e4a687d6d55e98772bd3f7c8b1da7 /vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go | |
parent | bump ncruces/go-sqlite3 to v0.21.1 (#3625) (diff) | |
download | gotosocial-c953f57e55810fa0e3201a67a4622fe4ac39c278.tar.xz |
update ncruces/go-sqlite3 to v0.21.2 (#3626)
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go')
-rw-r--r-- | vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go index 8e7f27084..10d6dbf61 100644 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go +++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go @@ -4,7 +4,9 @@ package vfs import ( "context" + "errors" "io" + "io/fs" "os" "sync" @@ -71,23 +73,21 @@ func (s *vfsShm) shmOpen() _ErrorCode { return _OK } - // Always open file read-write, as it will be shared. - f, err := os.OpenFile(s.path, - os.O_RDWR|os.O_CREATE|_O_NOFOLLOW, 0666) - if err != nil { - return _CANTOPEN - } - // Closes file if it's not nil. + var f *os.File + // Close file on error. + // Keep this here to avoid confusing checklocks. defer func() { f.Close() }() - fi, err := f.Stat() - if err != nil { - return _IOERR_FSTAT - } - vfsShmListMtx.Lock() defer vfsShmListMtx.Unlock() + // Stat file without opening it. + // Closing it would release all POSIX locks on it. + fi, err := os.Stat(s.path) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return _IOERR_FSTAT + } + // Find a shared file, increase the reference count. for _, g := range vfsShmList { if g != nil && os.SameFile(fi, g.info) { @@ -97,13 +97,33 @@ func (s *vfsShm) shmOpen() _ErrorCode { } } - // Lock and truncate the file. - // The lock is only released by closing the file. - if rc := osLock(f, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK); rc != _OK { + // Always open file read-write, as it will be shared. + f, err = os.OpenFile(s.path, + os.O_RDWR|os.O_CREATE|_O_NOFOLLOW, 0666) + if err != nil { + return _CANTOPEN + } + + // Dead man's switch. + if lock, rc := osTestLock(f, _SHM_DMS, 1); rc != _OK { + return _IOERR_LOCK + } else if lock == unix.F_WRLCK { + return _BUSY + } else if lock == unix.F_UNLCK { + if rc := osWriteLock(f, _SHM_DMS, 1); rc != _OK { + return rc + } + if err := f.Truncate(0); err != nil { + return _IOERR_SHMOPEN + } + } + if rc := osReadLock(f, _SHM_DMS, 1); rc != _OK { return rc } - if err := f.Truncate(0); err != nil { - return _IOERR_SHMOPEN + + fi, err = f.Stat() + if err != nil { + return _IOERR_FSTAT } // Add the new shared file. @@ -157,7 +177,30 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode { s.Lock() defer s.Unlock() - return s.shmMemLock(offset, n, flags) + + // Check if we could obtain/release the lock locally. + rc := s.shmMemLock(offset, n, flags) + if rc != _OK { + return rc + } + + // Obtain/release the appropriate file lock. + switch { + case flags&_SHM_UNLOCK != 0: + return osUnlock(s.File, _SHM_BASE+int64(offset), int64(n)) + case flags&_SHM_SHARED != 0: + rc = osReadLock(s.File, _SHM_BASE+int64(offset), int64(n)) + case flags&_SHM_EXCLUSIVE != 0: + rc = osWriteLock(s.File, _SHM_BASE+int64(offset), int64(n)) + default: + panic(util.AssertErr()) + } + + // Release the local lock. + if rc != _OK { + s.shmMemLock(offset, n, flags^(_SHM_UNLOCK|_SHM_LOCK)) + } + return rc } func (s *vfsShm) shmUnmap(delete bool) { |