Skip to content

guard vfsMap with a mutex - #19

Open
maxencehenneron wants to merge 1 commit into
psanford:mainfrom
maxencehenneron:main
Open

guard vfsMap with a mutex#19
maxencehenneron wants to merge 1 commit into
psanford:mainfrom
maxencehenneron:main

Conversation

@maxencehenneron

Copy link
Copy Markdown

Guard vfsMap with a mutex

vfsMap is written by newVFS (on RegisterVFS) and read by vfsFromC on every VFS callback, with no synchronization. Registering a VFS on one goroutine while another VFS's callbacks are in flight is a concurrent map read/write, which the Go runtime turns into a hard, unrecoverable crash of the whole process.

We hit this in production under load: connections open databases on many independently-registered VFSes concurrently, and a registration racing an in-flight xAccess brought the process down:

fatal error: concurrent map read and map write
goroutine 24874 [running, locked to thread]:
internal/runtime/maps.fatal(...)
        /usr/local/go/src/runtime/panic.go:1046
github.com/psanford/sqlite3vfs.vfsFromC(...)
        sqlite3vfscgo.go:488
github.com/psanford/sqlite3vfs.goVFSAccess(0xc00f0ddc88?, 0x7d21f4022865, ...)
        sqlite3vfscgo.go:93
github.com/mattn/go-sqlite3._Cfunc__sqlite3_step_internal(...)
        _cgo_gotypes.go:443
...

fileMap already has fileMux; vfsMap had nothing.

Fix

Add a sync.RWMutex around vfsMap: write-lock the assignment in newVFS, read-lock the lookup in vfsFromC. Registration is rare and lookups are on the hot path, so RWMutex keeps callbacks contention-free against each other.

registering a new vfs writes vfsMap while callbacks read it from other
threads, which trips the runtime concurrent map access check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant