Commit f39e846
committed
Fix M1: stale pooled handle can corrupt the pool under double-close/use-after-close
A pooled Query/Sender handle was the reused per-slot object itself, guarded
only by a non-volatile in-use/borrowed flag. Once a worker/slot was released
and re-borrowed, that flag flips back to "live", so a stale handle's
close()/cancel()/write would leak into a *different* borrow: a duplicate close
double-released the worker/slot (enqueued twice -> two concurrent borrowers on
one non-thread-safe client/delegate), and a cached Completion.cancel() or stale
write hit whatever borrow now owns it. Idempotent close() and no-op cancel()
are documented contracts, so this was reachable from contract-legal code, not
just misuse, with pool-wide blast radius and no -ea guard.
Fix: give every borrow its own immutable generation, stamped under the pool
lock when the worker/slot is handed out and bumped again when it is returned.
The reused state stays on the slot; callers get a thin per-borrow handle that
carries the generation and validates it on every operation:
- close()/cancel() are no-ops on a stale generation (idempotency preserved),
- submit()/data writes throw,
- release/giveBack/discardBroken re-check the generation under the pool lock
so a worker/slot can never be enqueued twice, plus an -ea assert that it is
not already in the available deque.
Egress: QueryImpl stops being the user-facing Query; new QueryLease wraps it.
Ingest: new SenderSlot is the reused slot; PooledSender becomes the per-borrow
wrapper (keeps the public name, so borrow() still returns it). The per-submit
path stays allocation-free; only the small lease handle is created per borrow
(routinely scalar-replaced under try-with-resources).
Adds QueryLeaseGenerationTest and SenderLeaseGenerationTest covering the
double-release and cross-borrow cancel/write paths; updates the white-box
tests to the new shapes. Full core suite green under -ea (the lone failure is
the unrelated pre-existing FilesTest M2, which fails identically on master).1 parent 65e4912 commit f39e846
15 files changed
Lines changed: 937 additions & 311 deletions
File tree
- core/src
- main/java/io/questdb/client
- impl
- test/java/io/questdb/client/test/impl
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
39 | | - | |
40 | | - | |
41 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
42 | 44 | | |
43 | 45 | | |
44 | 46 | | |
| |||
83 | 85 | | |
84 | 86 | | |
85 | 87 | | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
90 | 92 | | |
91 | 93 | | |
92 | 94 | | |
| |||
0 commit comments