summaryrefslogtreecommitdiff
path: root/vendor/github.com/ncruces/go-sqlite3/vfs
diff options
context:
space:
mode:
authorLibravatar kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>2024-12-17 23:16:20 +0000
committerLibravatar GitHub <noreply@github.com>2024-12-17 23:16:20 +0000
commitc953f57e55810fa0e3201a67a4622fe4ac39c278 (patch)
tree6b059966b98e4a687d6d55e98772bd3f7c8b1da7 /vendor/github.com/ncruces/go-sqlite3/vfs
parentbump ncruces/go-sqlite3 to v0.21.1 (#3625) (diff)
downloadgotosocial-c953f57e55810fa0e3201a67a4622fe4ac39c278.tar.xz
update ncruces/go-sqlite3 to v0.21.2 (#3626)
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/vfs')
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/README.md5
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go37
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go15
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/shm_bsd.go79
-rw-r--r--vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go10
5 files changed, 105 insertions, 41 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/README.md b/vendor/github.com/ncruces/go-sqlite3/vfs/README.md
index 354f8bf33..4e987ce3f 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/README.md
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/README.md
@@ -48,11 +48,6 @@ On Unix, this package may use `mmap` to implement
[shared-memory for the WAL-index](https://sqlite.org/wal.html#implementation_of_shared_memory_for_the_wal_index),
like SQLite.
-With [BSD locks](https://man.freebsd.org/cgi/man.cgi?query=flock&sektion=2)
-a WAL database can only be accessed by a single proccess.
-Other processes that attempt to access a database locked with BSD locks,
-will fail with the [`SQLITE_PROTOCOL`](https://sqlite.org/rescode.html#protocol) error code.
-
On Windows, this package may use `MapViewOfFile`, like SQLite.
You can also opt into a cross-platform, in-process, memory sharing implementation
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go
index fa13ef3ae..4f6fadef4 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_bsd.go
@@ -9,11 +9,11 @@ import (
)
func osGetSharedLock(file *os.File) _ErrorCode {
- return osLock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK)
+ return osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK)
}
func osGetReservedLock(file *os.File) _ErrorCode {
- rc := osLock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
+ rc := osFlock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
if rc == _BUSY {
// The documentation states that a lock is upgraded by
// releasing the previous lock, then acquiring the new lock.
@@ -37,7 +37,7 @@ func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode {
}
func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode {
- rc := osLock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK)
+ rc := osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK)
if rc == _BUSY {
// The documentation states that a lock is downgraded by
// releasing the previous lock then acquiring the new lock.
@@ -66,7 +66,36 @@ func osCheckReservedLock(file *os.File) (bool, _ErrorCode) {
return lock == unix.F_WRLCK, rc
}
-func osLock(file *os.File, how int, def _ErrorCode) _ErrorCode {
+func osFlock(file *os.File, how int, def _ErrorCode) _ErrorCode {
err := unix.Flock(int(file.Fd()), how)
return osLockErrorCode(err, def)
}
+
+func osReadLock(file *os.File, start, len int64) _ErrorCode {
+ return osLock(file, unix.F_RDLCK, start, len, _IOERR_RDLOCK)
+}
+
+func osWriteLock(file *os.File, start, len int64) _ErrorCode {
+ return osLock(file, unix.F_WRLCK, start, len, _IOERR_LOCK)
+}
+
+func osLock(file *os.File, typ int16, start, len int64, def _ErrorCode) _ErrorCode {
+ err := unix.FcntlFlock(file.Fd(), unix.F_SETLK, &unix.Flock_t{
+ Type: typ,
+ Start: start,
+ Len: len,
+ })
+ return osLockErrorCode(err, def)
+}
+
+func osUnlock(file *os.File, start, len int64) _ErrorCode {
+ err := unix.FcntlFlock(file.Fd(), unix.F_SETLK, &unix.Flock_t{
+ Type: unix.F_UNLCK,
+ Start: start,
+ Len: len,
+ })
+ if err != nil {
+ return _IOERR_UNLOCK
+ }
+ return _OK
+}
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go b/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go
index b00a1865b..7a9c38897 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/os_dotlk.go
@@ -7,6 +7,8 @@ import (
"io/fs"
"os"
"sync"
+
+ "github.com/ncruces/go-sqlite3/internal/dotlk"
)
var (
@@ -28,12 +30,10 @@ func osGetSharedLock(file *os.File) _ErrorCode {
name := file.Name()
locker := vfsDotLocks[name]
if locker == nil {
- f, err := os.OpenFile(name+".lock", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
- f.Close()
- if errors.Is(err, fs.ErrExist) {
- return _BUSY // Another process has the lock.
- }
- if err != nil {
+ if err := dotlk.TryLock(name + ".lock"); err != nil {
+ if errors.Is(err, fs.ErrExist) {
+ return _BUSY // Another process has the lock.
+ }
return _IOERR_LOCK
}
locker = &vfsDotLocker{}
@@ -114,8 +114,7 @@ func osReleaseLock(file *os.File, state LockLevel) _ErrorCode {
}
if locker.shared == 1 {
- err := os.Remove(name + ".lock")
- if err != nil && !errors.Is(err, fs.ErrNotExist) {
+ if err := dotlk.Unlock(name + ".lock"); err != nil {
return _IOERR_UNLOCK
}
delete(vfsDotLocks, name)
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) {
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go
index e302db7e6..17fefe562 100644
--- a/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go
+++ b/vendor/github.com/ncruces/go-sqlite3/vfs/shm_dotlk.go
@@ -6,11 +6,11 @@ import (
"context"
"errors"
"io/fs"
- "os"
"sync"
"github.com/tetratelabs/wazero/api"
+ "github.com/ncruces/go-sqlite3/internal/dotlk"
"github.com/ncruces/go-sqlite3/internal/util"
)
@@ -58,8 +58,7 @@ func (s *vfsShm) Close() error {
return nil
}
- err := os.Remove(s.path)
- if err != nil && !errors.Is(err, fs.ErrNotExist) {
+ if err := dotlk.Unlock(s.path); err != nil {
return _IOERR_UNLOCK
}
delete(vfsShmList, s.path)
@@ -82,9 +81,8 @@ func (s *vfsShm) shmOpen() _ErrorCode {
return _OK
}
- // Create a directory on disk to ensure only this process
- // uses this path to register a shared memory.
- err := os.Mkdir(s.path, 0777)
+ // Dead man's switch.
+ err := dotlk.LockShm(s.path)
if errors.Is(err, fs.ErrExist) {
return _BUSY
}