This is the record of an abcd-managed repository

abcdBetav0.16.2 · 2026-11-06

Development record

2026-10-16 — Refines dcn-2610162239308903, the load gate's queue (iss-2610161634043273), on the gap it accepted and on how far its no-cycle claim reaches. The gap is larger than that record says. Two waiters whose start and pid disagree, as after the process ids wrap, wait on neither, and across accounts no hold keeps them apart, so re-checks that fall in one moment, before either shows in the process table as running its command, both open, and their commands overlap. Under `--wait -- make preflight` the overlap becomes a stall: each preflight's own gate, the inner waiter that takes its running ancestor's place, still counts every other waiter running its command as ahead, so each waits on the other's outer waiter and both stand until their two-hour timeouts. It needs a pid wrap, two accounts and coinciding re-checks. The mitigation uses no shared file, which iss-2610140638074587 still rules out. The command form shows itself in the table as running its command from the moment it opens, by a short-lived child of the waiter (a /bin/sleep, its mark, stopped once the command has started), waits two seconds (WaitOpenPause) and reads the table once more before it starts its command. If another waiter is then running its command, opened within that pause and the start tolerance, and has the lower pid, this waiter stands back: it stops its mark, gives up its hold, re-draws its jitter and waits again, while the lower pid keeps going. Because each opener is marked from the moment it opens, two that open at the same instant each see the other, and exactly one runs. A waiter stands back at most three times (WaitBackoffCap) and then opens without the look, so no wait goes round for ever. The plain form starts no command and neither marks nor looks. Within one account nothing changes: the hold already admits one. What stays open: a mark that cannot be started, a table that cannot be read at the look, the cap, and a process start slower than the pause. Rejected: having only the lower pid look, since an opener cannot tell that it is the lower of a disagreeing pair; and closing the stall in the inner gate alone, which leaves two plain race runs overlapping. The earlier record's 'whatever mix of code' covers this code and the pid-only waiters built before the start-order change, and nothing else. A waiter still running the branch's first version, which ordered the queue by start alone, waits on a higher pid that started earlier and can deadlock against pid-only waiters, and no change here can break that, since that waiter never runs it. So when this lands, any waiter running that start-only build is stopped and requeued.

decisiondcn-2610162257477571

2026-10-16 — Refines dcn-2610162239308903, the load gate's queue (iss-2610161634043273), on the gap it accepted and on how far its no-cycle claim reaches. The gap is larger than that record says. Two waiters whose start and pid disagree, as after the process ids wrap, wait on neither, and across accounts no hold keeps them apart, so re-checks that fall in one moment, before either shows in the process table as running its command, both open, and their commands overlap. Under --wait -- make preflight the overlap becomes a stall: each preflight's own gate, the inner waiter that takes its running ancestor's place, still counts every other waiter running its command as ahead, so each waits on the other's outer waiter and both stand until their two-hour timeouts. It needs a pid wrap, two accounts and coinciding re-checks. The mitigation uses no shared file, which iss-2610140638074587 still rules out. The command form shows itself in the table as running its command from the moment it opens, by a short-lived child of the waiter (a /bin/sleep, its mark, stopped once the command has started), waits two seconds (WaitOpenPause) and reads the table once more before it starts its command. If another waiter is then running its command, opened within that pause and the start tolerance, and has the lower pid, this waiter stands back: it stops its mark, gives up its hold, re-draws its jitter and waits again, while the lower pid keeps going. Because each opener is marked from the moment it opens, two that open at the same instant each see the other, and exactly one runs. A waiter stands back at most three times (WaitBackoffCap) and then opens without the look, so no wait goes round for ever. The plain form starts no command and neither marks nor looks. Within one account nothing changes: the hold already admits one. What stays open: a mark that cannot be started, a table that cannot be read at the look, the cap, and a process start slower than the pause. Rejected: having only the lower pid look, since an opener cannot tell that it is the lower of a disagreeing pair; and closing the stall in the inner gate alone, which leaves two plain race runs overlapping. The earlier record's 'whatever mix of code' covers this code and the pid-only waiters built before the start-order change, and nothing else. A waiter still running the branch's first version, which ordered the queue by start alone, waits on a higher pid that started earlier and can deadlock against pid-only waiters, and no change here can break that, since that waiter never runs it. So when this lands, any waiter running that start-only build is stopped and requeued.

A further case stays open, named by the re-check review: the window the look uses (the pause plus the start tolerance) is measured from the look, not from the waiter's own re-check read. A waiter whose path from its re-check to its mark is slow under load can therefore discard a concurrent opener it did see, and both run; it is captured as iss-2610162306239284, with measuring the window from the re-check read as the fix.

Frontmatter

iddcn-2610162257477571
typedecision
date2026-10-16

mentions5