Co-authored-by: jason.woltje <jason@diversecanvas.com> Co-committed-by: jason.woltje <jason@diversecanvas.com>
This commit was merged in pull request #926.
This commit is contained in:
@@ -387,13 +387,58 @@ if command -v flock >/dev/null 2>&1; then
|
|||||||
"$STORE" init >/dev/null 2>&1 || true
|
"$STORE" init >/dev/null 2>&1 || true
|
||||||
o1="$TMP_ROOT/t10.o1"
|
o1="$TMP_ROOT/t10.o1"
|
||||||
o2="$TMP_ROOT/t10.o2"
|
o2="$TMP_ROOT/t10.o2"
|
||||||
# Two enqueues racing on the SAME store. Without the lock both read
|
# --- deterministic start barrier (#923 de-flake; NOT a sleep) --------------
|
||||||
# observed_seq=0 and allocate 1 (aliasing + a lost write); the lock serializes
|
# A plain `cmd & cmd & wait` gives no guarantee the two enqueues are ever
|
||||||
# the allocate+write so they get 1 and 2.
|
# truly in-flight together — the scheduler can run one to completion before
|
||||||
"$STORE" enqueue --class actionable --locators '{"c":1}' >"$o1" 2>/dev/null &
|
# the other is even forked, so the flock contention this test exists to
|
||||||
|
# prove is never really exercised. Force REAL concurrency: both children
|
||||||
|
# block on a shared start gate (an flock'd file — no sleep, no timing
|
||||||
|
# guess) until BOTH have confirmed they are launched and waiting; only then
|
||||||
|
# does the parent release the gate, so both race into store.sh's own
|
||||||
|
# enqueue lock at (as close to) the same instant as the scheduler allows.
|
||||||
|
gate="$TMP_ROOT/t10.gate"
|
||||||
|
r1="$TMP_ROOT/t10.ready1"
|
||||||
|
r2="$TMP_ROOT/t10.ready2"
|
||||||
|
rm -f "$r1" "$r2"
|
||||||
|
exec 6>"$gate"
|
||||||
|
flock -x 6 # gate CLOSED: a shared-locker below blocks here until released.
|
||||||
|
|
||||||
|
(
|
||||||
|
: >"$r1" # "child 1 is launched and about to block on the gate"
|
||||||
|
exec 7<"$gate"
|
||||||
|
flock -s 7 # blocks until the parent drops its exclusive lock
|
||||||
|
flock -u 7
|
||||||
|
exec 7<&-
|
||||||
|
"$STORE" enqueue --class actionable --locators '{"c":1}'
|
||||||
|
) >"$o1" 2>/dev/null &
|
||||||
p1=$!
|
p1=$!
|
||||||
"$STORE" enqueue --class actionable --locators '{"c":2}' >"$o2" 2>/dev/null &
|
(
|
||||||
|
: >"$r2"
|
||||||
|
exec 7<"$gate"
|
||||||
|
flock -s 7
|
||||||
|
flock -u 7
|
||||||
|
exec 7<&-
|
||||||
|
"$STORE" enqueue --class actionable --locators '{"c":2}'
|
||||||
|
) >"$o2" 2>/dev/null &
|
||||||
p2=$!
|
p2=$!
|
||||||
|
|
||||||
|
# Busy-poll (NOT a sleep — no timing assumption) until BOTH children have
|
||||||
|
# confirmed they are launched and blocked on the gate, so the contention
|
||||||
|
# window below is genuine rather than incidental.
|
||||||
|
spins=0
|
||||||
|
while [ ! -e "$r1" ] || [ ! -e "$r2" ]; do
|
||||||
|
spins=$((spins + 1))
|
||||||
|
if [ "$spins" -gt 2000000 ]; then
|
||||||
|
fail_msg "T10: start barrier never saw both children launch — cannot construct genuine concurrency"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Release the gate: both children's pending shared-lock acquisitions are
|
||||||
|
# granted together, so they race into store.sh's OWN enqueue lock for real.
|
||||||
|
flock -u 6
|
||||||
|
exec 6>&-
|
||||||
|
|
||||||
wait "$p1"; wait "$p2"
|
wait "$p1"; wait "$p2"
|
||||||
a="$(tr -d '[:space:]' <"$o1")"
|
a="$(tr -d '[:space:]' <"$o1")"
|
||||||
b="$(tr -d '[:space:]' <"$o2")"
|
b="$(tr -d '[:space:]' <"$o2")"
|
||||||
|
|||||||
Reference in New Issue
Block a user