fix(wake): #927 enqueue TOCTOU — move stale-tmp cleanup off the hot enqueue path (no concurrent in-flight-write clobber) (#928)
Co-authored-by: jason.woltje <jason@diversecanvas.com> Co-committed-by: jason.woltje <jason@diversecanvas.com>
This commit was merged in pull request #928.
This commit is contained in:
@@ -75,8 +75,31 @@
|
||||
# distinct enumerations never collapse (§2.3/T2/G3-R6 intact); the
|
||||
# rejected class=digest alternative would have silently coalesced
|
||||
# them. store.sh and reconcile.sh are UNCHANGED by 0.6.4.
|
||||
# 0.6.5 #927 enqueue TOCTOU fix — move stale-tmp cleanup OFF the hot enqueue
|
||||
# path (no concurrent in-flight-write clobber). cmd_enqueue called
|
||||
# _wake_init_dir() (which reaped EVERY .wake.tmp.* unconditionally)
|
||||
# BEFORE taking the enqueue lock, so a 2nd enqueue's PRE-LOCK cleanup
|
||||
# deleted the LIVE in-flight tmp of a 1st enqueue holding the lock
|
||||
# through its atomic write -> spurious "durable pending write FAILED"
|
||||
# abort of a valid enqueue (reachable under live co-feed: detector +
|
||||
# reconciler concurrently enqueue). FIX (_wake-common.sh): (a)
|
||||
# _wake_init_dir no longer reaps tmps — it only ensures the layout,
|
||||
# so nothing on the enqueue/consume/cursors/ack hot paths can clobber
|
||||
# a concurrent live write; (b) _wake_clean_stale_tmp is AGE-SCOPED
|
||||
# (mmin +${WAKE_TMP_STALE_MIN:-5}) so it can only remove demonstrably-
|
||||
# orphaned crash-left tmps, never a live (ms-old) in-flight write.
|
||||
# Reaping now runs as an explicit MAINTENANCE action at store.sh init
|
||||
# (daemon-start) and the detector poll tick (detector.sh), keeping
|
||||
# accumulation bounded once-per-pass instead of raced per-enqueue.
|
||||
# #908 seq-integrity is UNCHANGED (single store-side allocator,
|
||||
# atomic allocate+enqueue under flock, arrow-1 no-burn, anti-swallow
|
||||
# fail-loud). reconcile.sh is UNCHANGED (its enumeration retry is the
|
||||
# structural recovery net: an aborted enqueue advances neither the
|
||||
# seen-ledger nor observed_seq, so the source is re-enumerated next
|
||||
# cycle — no obligation loss). Files changed: _wake-common.sh,
|
||||
# store.sh, detector.sh (+ tests).
|
||||
component=wake
|
||||
version=0.6.4
|
||||
version=0.6.5
|
||||
|
||||
# Watch-list schema this component consumes, and the INCLUSIVE range of
|
||||
# schema_version values it supports. A wake-watch-list.json whose schema_version
|
||||
@@ -87,7 +110,9 @@ schema_min=1
|
||||
schema_max=1
|
||||
|
||||
# Pieces shipped by this component version (informational):
|
||||
# store.sh A2 — three-cursor durable store + drain lib. (W2)
|
||||
# store.sh A2 — three-cursor durable store + drain lib. Stale-tmp reaping is
|
||||
# OFF the hot enqueue path; `init` performs the age-scoped
|
||||
# maintenance reap (#927). (W2, #927)
|
||||
# ack.sh A4 — RECEIVED/CONSUMED ack-wrapper (local-write + ship). (W2)
|
||||
# digest.sh A3 — cumulative-state digest renderer (hard locators,
|
||||
# two-tier trust, injection/secret scrub). PER-ENTRY
|
||||
@@ -100,7 +125,8 @@ schema_max=1
|
||||
# detector.sh A1 — per-host single-instance delta-gated detector daemon
|
||||
# (flock, anchor-scoped hashing, fail-loud source semantics;
|
||||
# enqueues deltas to store.sh and captures the store-allocated
|
||||
# observed_seq — no private counter, #908). (W4)
|
||||
# observed_seq — no private counter, #908). Its poll tick also
|
||||
# runs the age-scoped maintenance stale-tmp reap (#927). (W4)
|
||||
# fn-oracle.sh A6 — synthetic-canary FN-oracle: injects a KNOWN delta at the
|
||||
# source boundary, drives the pipeline through the detector's
|
||||
# public poll-once, asserts CONSUMED within the per-class SLO
|
||||
|
||||
Reference in New Issue
Block a user