fix: address Copilot review round 2 (#2339)

- The holder-record removal is best-effort and can no longer throw past
  release(); ERELEASED on release is the library having already dropped a
  taken-over lock, so it is ignored rather than described as a lock that
  "goes stale on its own".
- The signal test's stand-in now spawns a descendant of its own, so the
  whole-process-group guarantee is what the test asserts: a regression to
  child.kill() or a non-detached spawn leaves the descendant alive and fails.
- The three docs no longer claim a dead holder is always recovered in 30s:
  a stale lock directory that cannot be removed runs the wait to its
  45-minute cap and names the path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PsmUAZ6aLUAFqenjJKSSRp
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-12 22:30:05 -04:00
commit 2c8dbd3cd0

View file

@ -444,12 +444,21 @@ export async function runUnderLease({
// waiter reading a fresh lock must not be told about the previous
// holder — unless the lock is no longer ours, in which case the record
// is the winner's too.
if (guarded.mine()) rmSync(leaseTarget(dir), { force: true });
try {
if (guarded.mine()) rmSync(leaseTarget(dir), { force: true });
} catch {
// Diagnostic only; never let it stand between a finished gate and the
// release below.
}
try {
await release();
} catch (err) {
// `ERELEASED` means the library's own refresh tick already found the
// lock taken over and dropped it; the directory there now is the
// winner's live lock, and `onCompromised` has already said so.
if (err?.code === "ERELEASED") return;
log(
`gate-lease: could not release the lease (${err?.message ?? err}); it goes stale on its own after ${formatDuration(STALE_MS)}.`,
`gate-lease: could not release the lease (${err?.message ?? err}). A waiter takes it over once it is ${formatDuration(STALE_MS)} stale — unless whatever blocked this removal persists, in which case remove ${lockPathOf(dir)} by hand.`,
);
}
log(