diff --git a/internal/testcfg/testcfg.go b/internal/testcfg/testcfg.go index fb5cbdc3..e5acfb7c 100644 --- a/internal/testcfg/testcfg.go +++ b/internal/testcfg/testcfg.go @@ -19,7 +19,8 @@ func init() { path := filepath.Join(os.TempDir(), "wazero") if err := os.MkdirAll(path, 0777); err == nil { if cache, err := wazero.NewCompilationCacheWithDir(path); err == nil { - sqlite3.RuntimeConfig.WithCompilationCache(cache) + sqlite3.RuntimeConfig = sqlite3.RuntimeConfig. + WithCompilationCache(cache) } } } diff --git a/vfs/shm.go b/vfs/shm.go index 9affac05..d46c4228 100644 --- a/vfs/shm.go +++ b/vfs/shm.go @@ -22,8 +22,5 @@ func NewSharedMemory(path string, flags OpenFlag) SharedMemory { if flags&OPEN_MAIN_DB == 0 || flags&(OPEN_DELETEONCLOSE|OPEN_MEMORY) != 0 { return nil } - return &vfsShm{ - path: path, - readOnly: flags&OPEN_READONLY != 0, - } + return &vfsShm{path: path} } diff --git a/vfs/shm_bsd.go b/vfs/shm_bsd.go index a093cc42..34f1bdd6 100644 --- a/vfs/shm_bsd.go +++ b/vfs/shm_bsd.go @@ -18,11 +18,9 @@ type vfsShmFile struct { *os.File info os.FileInfo - // +checklocks:vfsShmFilesMtx - refs int + refs int // +checklocks:vfsShmFilesMtx - // +checklocks:Mutex - lock [_SHM_NLOCK]int16 + lock [_SHM_NLOCK]int16 // +checklocks:Mutex sync.Mutex } @@ -34,10 +32,9 @@ var ( type vfsShm struct { *vfsShmFile - path string - lock [_SHM_NLOCK]bool - regions []*util.MappedRegion - readOnly bool + path string + lock [_SHM_NLOCK]bool + regions []*util.MappedRegion } func (s *vfsShm) Close() error { @@ -69,7 +66,7 @@ func (s *vfsShm) Close() error { panic(util.AssertErr()) } -func (s *vfsShm) shmOpen() (rc _ErrorCode) { +func (s *vfsShm) shmOpen() _ErrorCode { if s.vfsShmFile != nil { return _OK } @@ -100,17 +97,13 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) { } } - // Lock and truncate the file, if not readonly. + // Lock and truncate the file. // The lock is only released by closing the file. - if s.readOnly { - rc = _READONLY_CANTINIT - } else { - if rc := osLock(f, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK); rc != _OK { - return rc - } - if err := f.Truncate(0); err != nil { - return _IOERR_SHMOPEN - } + if rc := osLock(f, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK); rc != _OK { + return rc + } + if err := f.Truncate(0); err != nil { + return _IOERR_SHMOPEN } // Add the new shared file. @@ -122,11 +115,11 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) { for i, g := range vfsShmFiles { if g == nil { vfsShmFiles[i] = s.vfsShmFile - return rc + return _OK } } vfsShmFiles = append(vfsShmFiles, s.vfsShmFile) - return rc + return _OK } func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, _ErrorCode) { @@ -148,25 +141,17 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext if !extend { return 0, _OK } - if s.readOnly || osAllocate(s.File, n) != nil { + if osAllocate(s.File, n) != nil { return 0, _IOERR_SHMSIZE } } - var prot int - if s.readOnly { - prot = unix.PROT_READ - } else { - prot = unix.PROT_READ | unix.PROT_WRITE - } - r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, prot) + r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, + unix.PROT_READ|unix.PROT_WRITE) if err != nil { return 0, _IOERR_SHMMAP } s.regions = append(s.regions, r) - if s.readOnly { - return r.Ptr, _READONLY - } return r.Ptr, _OK } diff --git a/vfs/shm_copy.go b/vfs/shm_dotlk.go similarity index 89% rename from vfs/shm_copy.go rename to vfs/shm_dotlk.go index 4285f0ba..a4f44ea6 100644 --- a/vfs/shm_copy.go +++ b/vfs/shm_dotlk.go @@ -4,6 +4,9 @@ package vfs import ( "context" + "errors" + "io/fs" + "os" "sync" "unsafe" @@ -29,15 +32,14 @@ var ( type vfsShm struct { *vfsShmBuffer - mod api.Module - alloc api.Function - free api.Function - path string - shadow []byte - ptrs []uint32 - stack [1]uint64 - lock [_SHM_NLOCK]bool - readOnly bool + mod api.Module + alloc api.Function + free api.Function + path string + shadow []byte + ptrs []uint32 + stack [1]uint64 + lock [_SHM_NLOCK]bool } func (s *vfsShm) Close() error { @@ -58,13 +60,18 @@ func (s *vfsShm) Close() error { return nil } + err := os.Remove(s.path) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return _IOERR_UNLOCK + } delete(vfsShmBuffers, s.path) + s.vfsShmBuffer = nil return nil } -func (s *vfsShm) shmOpen() { +func (s *vfsShm) shmOpen() _ErrorCode { if s.vfsShmBuffer != nil { - return + return _OK } vfsShmBuffersMtx.Lock() @@ -74,12 +81,23 @@ func (s *vfsShm) shmOpen() { if g, ok := vfsShmBuffers[s.path]; ok { s.vfsShmBuffer = g g.refs++ - return + 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) + if errors.Is(err, fs.ErrExist) { + return _BUSY + } + if err != nil { + return _IOERR_LOCK } // Add the new shared buffer. s.vfsShmBuffer = &vfsShmBuffer{} vfsShmBuffers[s.path] = s.vfsShmBuffer + return _OK } func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, _ErrorCode) { @@ -91,8 +109,10 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext s.free = mod.ExportedFunction("sqlite3_free") s.alloc = mod.ExportedFunction("sqlite3_malloc64") } + if rc := s.shmOpen(); rc != _OK { + return 0, rc + } - s.shmOpen() s.Lock() defer s.Unlock() defer s.shmAcquire() diff --git a/vfs/shm_ofd.go b/vfs/shm_ofd.go index 019fc7ab..31f6a91d 100644 --- a/vfs/shm_ofd.go +++ b/vfs/shm_ofd.go @@ -28,14 +28,13 @@ var _ blockingSharedMemory = &vfsShm{} func (s *vfsShm) shmOpen() _ErrorCode { if s.File == nil { - var flag int - if s.readOnly { - flag = unix.O_RDONLY - } else { - flag = unix.O_RDWR - } f, err := os.OpenFile(s.path, - flag|unix.O_CREAT|unix.O_NOFOLLOW, 0666) + unix.O_RDWR|unix.O_CREAT|unix.O_NOFOLLOW, 0666) + if err != nil { + f, err = os.OpenFile(s.path, + unix.O_CREAT|unix.O_NOFOLLOW, 0666) + s.readOnly = true + } if err != nil { return _CANTOPEN }