Skip to content

[tx] Dead-thread cleanup discards transactions without rollback; explicit file locks leak forever #4941

Closed

Description

@lvca

Severity: MEDIUM

Location: DatabaseContext.java:190-195 (cleanupDeadThreads only prunes the CONTEXTS map), utility/LockManager (ownership keyed by requester with no liveness sweep / timeout), TransactionContext.java:519-530 (kill() nulls lockedFiles without unlocking).

A thread acquires an explicit lock (acquireLock().type("X").lock()), then dies from an uncaught error before commit/rollback. cleanupDeadThreads removes its context, dropping the only reference to explicitLockedFiles. The LockManager entries remain owned by the dead requester forever; every later commit touching those files times out with LockTimeoutException until restart.

Fix: in cleanupDeadThreads/removeAllContexts, roll back any active TransactionContext found (which releases locks via reset()); optionally add a dead-owner sweep to LockManager for Thread requesters.


Filed from an internal engine deep-audit (2026-07). Traced to source; verify against current main before fixing and add a regression test.

Activity

  1. added
    auditFindings from the 2026-07 engine deep audit
    concurrencyThreading / concurrency / MVCC
    on Jul 3, 2026
  2. added this to the 26.8.1 milestone on Jul 4, 2026
  3. self-assigned this
    on Jul 6, 2026
  4. added theissue type on Jul 6, 2026
  5. added 4 commits that reference this issue on Jul 6, 2026
  6. lvca commented on Jul 7, 2026

    @lvca
    MemberAuthor

    Fixed in #5060 (merged). The dead-thread sweep now rolls back the transactions a dead thread abandoned - releasing their file locks - instead of just discarding the last reference to them (which left LockManager files owned by a dead requester forever; every later commit touching them timed out until restart). Exactly-once is guaranteed by a two-level atomic claim (the CONTEXTS entry against concurrent sweepers, the per-database key against closeInternal's removeAllContexts), rollback failures log a WARNING with cause/thread/database instead of being swallowed (a failed rollback is precisely this leak persisting), and a sweep that did real work emits one attributable summary WARNING. Red-first verified: both explicit-lock leak tests failed on old code with LockTimeoutException. Nine review rounds hardened the JMM story end to end.

  7. added a commit that references this issue on Jul 7, 2026
  8. added 3 commits that reference this issue on Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

auditFindings from the 2026-07 engine deep auditbugconcurrencyThreading / concurrency / MVCC

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions