Skip to content

fix(detector/vuls2): share opened db session across server requests#2544

Closed
MaineK00n wants to merge 1 commit into
masterfrom
fix/vuls2-shared-session
Closed

fix(detector/vuls2): share opened db session across server requests#2544
MaineK00n wants to merge 1 commit into
masterfrom
fix/vuls2-shared-session

Conversation

@MaineK00n
Copy link
Copy Markdown
Collaborator

Summary

  • Fixes Concurrency issue in boltdb handling #2542 — concurrent requests to vuls server with the vuls2 BoltDB backend hung for several minutes once concurrency reached ~4-5.
  • Each HTTP request opened the BoltDB file up to four times (twice in newDBConfig validation, plus the caller's session in both Detect and EnrichVulnInfos). Every open acquires the OS-level file lock and rebuilds the WithCache: true session cache, so concurrent requests serialized against each other.
  • Open the vuls2 db session lazily on first use, validate metadata once, and share the same opened session across subsequent callers. The cached session is released at server shutdown via the new vuls2.CloseSession.

Why only vuls2

go-cve-dictionary and gost follow the same per-request open/close pattern, but their backends sidestep the cost (Redis / HTTP / SQLite3-with-WAL / RDBMS connection pools), so the issue does not manifest in practice. vuls2 is BoltDB-only and additionally re-initializes a WithCache: true cache per open, making the per-request pattern a real bottleneck — hence the targeted fix here.

When cveDict/gost are eventually folded into vuls2 (à la go-msfdb / go-exploitdb), the natural follow-up is to expose the session as an explicit argument and remove the package-level cache; today's internal getSession does not lock that direction in.

Trade-offs / notes

  • Long-running servers with SkipUpdate = false will hold the db opened at startup for the lifetime of the process. This matches today's effective behavior (the per-request opens still saw only the snapshot they validated against) and is consistent with the existing recommendation to use SkipUpdate = true in server mode.
  • CloseSession is invoked from subcmds/server.go via defer. Process termination by signal will not run the defer, but the OS releases the BoltDB file lock on exit anyway — adding a signal handler is out of scope for this fix.

Test plan

  • go build ./...
  • go vet ./detector/vuls2/... ./subcmds/... ./server/...
  • go test ./detector/vuls2/...
  • Manual: run vuls server against a real vuls2 db, fire concurrent requests (e.g. seq 1 8 | xargs -P8 -I{} curl -X POST ...) and confirm response time stays roughly linear in payload size rather than blowing up with concurrency.

🤖 Generated with Claude Code

Per-request bolt.Open() on the vuls2 BoltDB acquired the OS-level file
lock and rebuilt the WithCache:true session cache on every HTTP request,
serializing concurrent `vuls server` requests and causing minutes-long
latency at concurrency >= 4-5 (#2542). Each request opened the file four
times: twice in newDBConfig (validate-then-close, then again for the
caller) for both Detect and EnrichVulnInfos.

Open the session lazily on first use, validate metadata once, and reuse
the same opened session for subsequent callers. Server mode closes the
cached session at shutdown via the new vuls2.CloseSession.
@MaineK00n MaineK00n marked this pull request as draft May 8, 2026 07:34
@MaineK00n MaineK00n closed this May 10, 2026
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.

Concurrency issue in boltdb handling

1 participant