Regenerate pot/xx/ko after Phase 4 C* (drop blob headers; add per-label
msgids). Row right-just must use RightJustifyNumber — mux_vsnprintf does
not implement %* width (#1429), so the filed %*d/%*lld path would echo
literally and drop the rest of each stats line.
Two constant alloc_notify chrome lines in alloc.cpp (corruption abort
banner and buffer-stats header). Leave tprintf formats as T().
Regenerate pot/xx without fuzzy entries.
Pass B1 + H1 residual — bugs 2.13-era code often just lived with.
H1: pool freelist corruption used to clear the *entire* free stack
(leaking every still-valid free buffer). Drop only the bad entry.
H1: mux_alarm set/sleep used long ReturnMilliseconds() (Win32 truncate
for long deltas). Use int64_t from 100ns ticks and clamp.
B1: kqueue/IOCP/wselect now warn when IPV6_V6ONLY dual-stack fails,
matching epoll/select (#739 family).
Closes#1289.
JIT: document dispatch-only alarm polling; emit #-1 CPU LIMITED on
wall-clock abort (shared_heap/run_compiled/run_cached_program); static
invocation-count watermark (bail_invk) analogous to #1002 depth; note
bail_longreg as legacy after the longbit diamond.
Defense: site_connection_count and forbid_site use same_source_key /
nospam_connect; graduated list text distinguishes exemption vs restrict
thresholds; pool budget policy matches permanent soft-ceiling reality;
login-throttle indent and input_limit hysteresis edge fixed.
Pre-auth cap now keys on same_source_key (IPv4 host / IPv6 /64) so a
single /64 cannot fan out past max_preauth_sitecons. connect_rate_charge
runs only after pre-auth acceptance, matching the "charge accepted only"
invariant. Equal-subnet site inserts adopt ulThreshold so graduated
thresholds can be reconfigured without reset_site. Defense knobs use
cf_live_driver_int + a libmux driver-config sync callback so @admin
updates g_dc without a restart.
Backstop for the pool_alloc -> fatal OutOfMemory cliff
(docs/survey-resource-defenses.md gap #3). pool_alloc/pool_alloc_lbuf
take memory from the system only on the slow path (freelist empty) and
never return it, so the process's pool footprint is its PEAK CONCURRENT
buffer count. New pool_memory_limit config (bytes; K/M/G suffixes;
0=unlimited) caps that footprint: on the slow path, crossing it trips
the same cooperative per-command abort the wall-clock alarm uses
(alarm_clock.alarmed, reachable from alloc.cpp — both are libmux) so a
runaway command unwinds and frees its buffers back to the freelist
instead of the server aborting on OutOfMemory. Composes with the JIT
wall-clock alarm (same flag). cf_pool_limit pushes the value to the
libmux global on load and @readcache reload.
Off by default, and honestly so: measurement showed the cliff is HARD
TO REACH, which is the point — the interpreter's alloc-and-free
discipline, bounded nesting (func_nest_lim/nStackLimit), and freelist
reuse keep peak pool footprint tiny (a short session didn't cross even
256KB). And no non-zero default is safe across deployments (a 256MB
VPS vs a 32GB host want different ceilings), so the admin sizes it.
Note: the nested-iter OS-OOM crash seen while building the JIT alarm is
a DIFFERENT path (JIT arena/guest growth, bounded by max_dispatch=10M
by default), not this one.
Verified default-off is a true no-op: smoke 1319/1319, oracle 9/9,
jit_diff 400/0, stress 8/8; the trip path is wired (server survives +
stays responsive when the budget is crossed).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eliminate the ISOUTOFMEMORY macro that unconditionally aborted on allocation
failure. Each of the 23 call sites now handles OOM appropriately:
- Fatal sites (buffer pools, db array, anum table): mux_assert or OutOfMemory
- Recoverable sites (queue, mail, commands, guests, vattrs, config, restart,
forward lists): log the failure and return gracefully
Also fix g_dump_child_pid portability: volatile pid_t -> volatile sig_atomic_t
with explicit casts in ganl_adapter.cpp.
Close integer overflow issue as false alarm (getstring_noalloc uses a bounded
static buffer, so nBuffer+1 cannot wrap).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the two-level manual reference counting system (lbuf_ref + reg_ref
with BufAddRef/BufRelease/RegAddRef/RegRelease) with std::shared_ptr:
- RegBuffer: new shared buffer struct, managed by shared_ptr — replaces
lbuf_ref which was a manual refcount wrapper around a pool-allocated lbuf
- reg_ref: now contains shared_ptr<RegBuffer> instead of lbuf_ref pointer;
allocated with new/delete instead of POOL_REGREF
- RegAssign: uses make_shared<RegBuffer> instead of alloc_lbuf + alloc_lbufref;
packing optimization preserved (multiple values in one RegBuffer)
- RegRelease: simplified to decrement + delete (shared_ptr destructor
handles buffer lifecycle automatically)
- BufAddRef/BufRelease: eliminated entirely — shared_ptr copy/destroy
handles all buffer reference counting
- POOL_LBUFREF, POOL_REGREF: eliminated (NUM_POOLS 9 → 7)
- JIT arena: uses shared_ptr<RegBuffer> instead of lbuf_ref
The pool allocator (POOL_LBUF) remains for the 323 temporary-buffer call
sites — that's the "blindingly fast" layer. The refcount layer above it
is now automatic via shared_ptr.
Net: −103 deleted, +51 added across 6 files. All 551 smoke tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Modernize the buffer pool allocator internals while keeping the
public API (alloc.h macros/functions) completely unchanged:
- POOLHDR: removed next/nxtfree intrusive list pointers (−16 bytes/buffer)
- POOL: chain_head/free_head → vector<char*> all_buffers/free_stack
- Alloc: pop_back from free_stack (O(1)), or new char[] + push to all_buffers
- Free: validate header/footer, push_back to free_stack (O(1))
- pool_vfy: iterate all_buffers vector — no longer silently truncates
the chain on corruption (the old "clearing freelist" behavior leaked
memory and was essentially untested defensive code)
- pool_reset: build unordered_set of free pointers, remove_if + delete[]
- pool_trace/list_bufstats: iterate all_buffers vector
Zero changes to alloc.h or any caller. All 551 smoke tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>