ouroboros/tests/test_lockfile_helpers.py
Anton Razzhigaev 98ca8a13d5 Retire completed campaign artifacts and keep repository reports explicit
Remove completed campaign records, one-time adoption/transplant machinery and
incidental line floors. Keep current contracts and generated inventories with
their readers, and direct optional domain reports to stdout or an explicit file.
Document continuing-purpose review in the existing handbook and checklists.

No version bump; ordinary release gates and runtime behavior are preserved.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-18 01:07:51 +03:00

882 lines
41 KiB
Python

import contextlib
import errno
import inspect
import os
import pathlib
import re
import threading
import time
import pytest
from ouroboros import platform_layer
from ouroboros.platform_layer import (
acquire_exclusive_file_lock,
refresh_exclusive_file_lock,
release_exclusive_file_lock,
unlink_lockfile,
)
def _steal(lock_path, text="pid=1 ts=stolen\n"):
"""Replace the lock file the way an evictor + a second acquirer would."""
lock_path.unlink()
lock_path.write_text(text, encoding="utf-8")
def test_release_without_fd_does_not_unlink_existing_lock(tmp_path):
lock_path = tmp_path / "state.lock"
lock_path.write_text("owned elsewhere", encoding="utf-8")
release_exclusive_file_lock(lock_path, None)
assert lock_path.read_text(encoding="utf-8") == "owned elsewhere"
def test_release_with_fd_unlinks_owned_lock(tmp_path):
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path, metadata="owned\n")
assert fd is not None
release_exclusive_file_lock(lock_path, fd)
assert not lock_path.exists()
def test_path_only_git_lock_cleanup_remains_available(tmp_path):
lock_path = tmp_path / "git.lock"
fd = acquire_exclusive_file_lock(lock_path, metadata="owned\n")
assert fd is not None
os.close(fd)
unlink_lockfile(lock_path)
assert not lock_path.exists()
# --- Ownership: a lock is only ever OURS to renew or remove -------------------
@pytest.mark.skipif(platform_layer.IS_WINDOWS, reason="the test itself unlinks or rewrites a lock file its owner holds open, which Windows refuses; the protocol it pins runs on both tiers of both OSes")
def test_release_never_unlinks_a_lock_that_was_stolen(tmp_path):
"""A hold evicted as stale must not delete the new owner's lock on exit."""
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path, metadata="pid=old ts=0\n")
assert fd is not None
_steal(lock_path)
release_exclusive_file_lock(lock_path, fd)
assert lock_path.read_text(encoding="utf-8") == "pid=1 ts=stolen\n"
@pytest.mark.skipif(platform_layer.IS_WINDOWS, reason="the test itself unlinks or rewrites a lock file its owner holds open, which Windows refuses; the protocol it pins runs on both tiers of both OSes")
def test_stale_eviction_never_removes_a_lock_re_created_under_it(tmp_path, monkeypatch):
"""Judge one file, unlink that same file — or none at all.
Between the staleness judgement and the unlink the real owner may release
and a third writer take the lock; removing THAT file would put two writers
on one authority.
"""
lock_path = tmp_path / "state.lock"
lock_path.write_text("pid=424242 ts=0\n", encoding="utf-8")
os.utime(lock_path, (0.0, 0.0)) # ancient: judged abandoned
def racing_alive(pid):
_steal(lock_path, "pid=999 ts=fresh\n")
return False # the judged owner really is gone
monkeypatch.setattr(platform_layer, "pid_is_alive", racing_alive)
fd = acquire_exclusive_file_lock(
lock_path, timeout_sec=0.3, stale_sec=1.0, poll_sec=0.02,
owner_aware_stale=True,
)
assert fd is None # the lock was not ours to take
assert lock_path.read_text(encoding="utf-8") == "pid=999 ts=fresh\n"
def test_stale_eviction_still_reclaims_a_genuinely_abandoned_lock(tmp_path, monkeypatch):
lock_path = tmp_path / "state.lock"
lock_path.write_text("pid=424242 ts=0\n", encoding="utf-8")
os.utime(lock_path, (0.0, 0.0))
monkeypatch.setattr(platform_layer, "pid_is_alive", lambda pid: False)
fd = acquire_exclusive_file_lock(
lock_path, timeout_sec=1.0, stale_sec=1.0, poll_sec=0.02,
owner_aware_stale=True,
)
assert fd is not None
release_exclusive_file_lock(lock_path, fd)
@pytest.mark.skipif(platform_layer.IS_WINDOWS, reason="kill(pid, 0) is the POSIX liveness probe")
def test_a_pid_that_refuses_our_signal_is_alive_and_its_lock_is_not_reclaimed(tmp_path, monkeypatch):
"""EPERM from ``kill(pid, 0)`` means the process EXISTS and merely refuses
our signal — another user's process on a shared host, or a pid recycled
onto one. Reading it as dead let the owner-aware stale rule evict such a
lock by age; it is alive, so the lock stays (the disclosed recycled-pid
wedge), and only ESRCH is a process provably gone."""
def answering(code):
def kill(pid, sig):
raise OSError(code, "kill refused")
return kill
monkeypatch.setattr(os, "kill", answering(errno.EPERM))
assert platform_layer.pid_is_alive(4242) is True and platform_layer.pid_provably_gone(4242) is False
lock_path = tmp_path / "state.lock"
lock_path.write_text("pid=4242 ts=0\n", encoding="utf-8")
os.utime(lock_path, (0.0, 0.0)) # aged past any staleness window
assert acquire_exclusive_file_lock(
lock_path, timeout_sec=0.3, stale_sec=1.0, poll_sec=0.02, owner_aware_stale=True,
) is None
assert lock_path.read_text(encoding="utf-8") == "pid=4242 ts=0\n"
monkeypatch.setattr(os, "kill", answering(errno.ESRCH))
assert platform_layer.pid_is_alive(4242) is False and platform_layer.pid_provably_gone(4242) is True
@pytest.mark.skipif(platform_layer.IS_WINDOWS, reason="the test itself unlinks or rewrites a lock file its owner holds open, which Windows refuses; the protocol it pins runs on both tiers of both OSes")
def test_heartbeat_reports_lost_ownership_instead_of_renewing(tmp_path):
"""The renewal is an OWNERSHIP statement: a stolen lock renews nothing."""
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path, metadata="pid=old ts=0\n")
assert fd is not None
assert refresh_exclusive_file_lock(lock_path, fd) is True
_steal(lock_path)
assert refresh_exclusive_file_lock(lock_path, fd) is False
os.close(fd)
@pytest.mark.skipif(platform_layer.IS_WINDOWS, reason="the test itself unlinks or rewrites a lock file its owner holds open, which Windows refuses; the protocol it pins runs on both tiers of both OSes")
def test_heartbeat_on_a_deleted_lock_reports_lost_ownership(tmp_path):
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path, metadata="pid=old ts=0\n")
assert fd is not None
lock_path.unlink()
assert refresh_exclusive_file_lock(lock_path, fd) is False
os.close(fd)
@pytest.mark.skipif(
platform_layer.IS_WINDOWS,
reason="the swap mechanism is POSIX: Windows cannot replace an open, "
"LockFileEx-held lock file",
)
def test_heartbeat_after_an_atomic_swap_of_the_lock_reports_false(tmp_path):
"""A thief that REPLACES the lock file atomically never leaves the path
absent, not even briefly — so any verdict weaker than an identity
comparison (an existence check, a successful utime) would renew a hold
that is no longer ours."""
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path, metadata="pid=old ts=0\n")
assert fd is not None
assert refresh_exclusive_file_lock(lock_path, fd) is True
imposter = tmp_path / "imposter.lock"
imposter.write_text("pid=1 ts=swapped\n", encoding="utf-8")
os.replace(imposter, lock_path)
assert refresh_exclusive_file_lock(lock_path, fd) is False
os.close(fd)
assert lock_path.read_text(encoding="utf-8") == "pid=1 ts=swapped\n"
@pytest.mark.skipif(
platform_layer.IS_WINDOWS,
reason="the eviction ORDER under test is POSIX: it unlinks under the held "
"flock, while Windows must close its probe first and leans on the new owner's "
"open handle across that gap (test_windows_evicts_a_stale_lock_only_under_the_probe_hold)",
)
def test_two_racing_reclaimers_never_yield_two_holders(tmp_path, monkeypatch):
"""Kernel-enforced eviction: judge, re-check and unlink happen under a
held flock on the very fd that was judged, so of two reclaimers racing
over one abandoned lock at most ONE may evict — the other either fails
the non-blocking flock or fails the inode re-check. Without the kernel
lock, a pause between the inode re-check and the unlink lets the second
reclaimer remove the first one's freshly won lock: two writers on one
monetary authority."""
lock_path = tmp_path / "state.lock"
lock_path.write_text("pid=424242 ts=0\n", encoding="utf-8")
os.utime(lock_path, (0.0, 0.0)) # ancient: judged abandoned by age
monkeypatch.setattr(platform_layer, "pid_is_alive", lambda pid: False)
stale_ident = platform_layer._lock_identity(lock_path)
barrier = threading.Barrier(2)
arrival_lock = threading.Lock()
arrivals: list = []
real_identity = platform_layer._lock_identity
def pausing_identity(target):
# The pause lands between the inode re-check (this read of the PATH's
# identity, still naming the judged stale file) and the unlink that
# trusts it. Both reclaimers are herded into the window together;
# the first to arrive then yields, so the second evicts and acquires
# while the first still believes its own, now stale, re-check.
result = real_identity(target)
if not isinstance(target, int) and result and result[:2] == stale_ident[:2]:
with contextlib.suppress(threading.BrokenBarrierError):
barrier.wait(timeout=0.4)
with arrival_lock:
first = not arrivals
arrivals.append(1)
if first:
time.sleep(0.15)
return result
monkeypatch.setattr(platform_layer, "_lock_identity", pausing_identity)
results: list = [None, None]
def reclaim(slot):
results[slot] = acquire_exclusive_file_lock(
lock_path, timeout_sec=2.0, stale_sec=1.0, poll_sec=0.01,
owner_aware_stale=True,
)
threads = [threading.Thread(target=reclaim, args=(slot,)) for slot in (0, 1)]
for thread in threads:
thread.start()
for thread in threads:
thread.join(timeout=10)
holders = [fd for fd in results if fd is not None]
assert len(holders) == 1, "two writers hold one monetary lock"
assert lock_path.exists()
release_exclusive_file_lock(lock_path, holders[0])
@pytest.mark.skipif(
platform_layer.IS_WINDOWS,
reason="flock-held eviction is POSIX; Windows cannot unlink a creator's open file",
)
def test_a_creator_evicted_while_lock_less_never_returns_a_descriptor(tmp_path, monkeypatch):
"""Between its O_EXCL create and its kernel lock a creator holds nothing an
evictor must respect: stalled there past ``stale_sec`` (SIGSTOP, a suspend,
clock skew) its fresh file is judged abandoned and evicted, and the lock it
then takes lands on an inode the path no longer names. That is not a hold:
the acquisition proves the path still names its descriptor and re-contends.
Belt: the owner pid is written BEFORE the lock, so an owner-aware reclaimer
never judges the live creator's file empty."""
lock_path = tmp_path / "state.lock"
monkeypatch.setattr(platform_layer, "_KERNEL_LOCK_TIER", {})
assert platform_layer.kernel_file_locks_enforced(lock_path) is True # decided before the hook
real_flock = platform_layer.file_lock_exclusive_nb
seen: dict = {}
def stalled_creator_flock(fd):
if not seen: # the creator's own first kernel lock: it stalls here
seen["metadata"] = lock_path.read_text(encoding="utf-8")
seen["reclaimer"] = None
os.utime(lock_path, (0.0, 0.0)) # the stall aged its lock-less file
seen["reclaimer"] = acquire_exclusive_file_lock( # an age-only reclaimer
lock_path, timeout_sec=2.0, stale_sec=1.0, poll_sec=0.01,
)
return real_flock(fd)
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", stalled_creator_flock)
creator = acquire_exclusive_file_lock(lock_path, timeout_sec=0.5, stale_sec=1.0, poll_sec=0.01)
holders = [fd for fd in (creator, seen["reclaimer"]) if fd is not None]
assert len(holders) == 1, "two descriptors believed to be one lock"
assert refresh_exclusive_file_lock(lock_path, holders[0]) is True
assert f"pid={os.getpid()}" in seen["metadata"] # known to any owner-aware evictor
release_exclusive_file_lock(lock_path, holders[0])
# --- Tiers: kernel-enforced or name-only, chosen by predicate, never by a refusal
def _tier(monkeypatch, enforced):
monkeypatch.setattr(
platform_layer, "kernel_file_locks_enforced", lambda path: enforced, raising=False,
)
def _refusing(code):
def refuse(fd):
raise OSError(code, "injected kernel refusal")
return refuse
def test_a_kernel_refusal_that_is_not_contention_fails_closed(tmp_path, monkeypatch):
"""On the enforced tier a descriptor the kernel would not lock is not a
hold: the acquisition answers None promptly (not after the timeout) and
removes the file it created, instead of degrading to the name protocol —
where the round-3 reclaimer race lives again."""
lock_path = tmp_path / "state.lock"
_tier(monkeypatch, True)
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", _refusing(errno.ENOLCK))
started = time.time()
fd = acquire_exclusive_file_lock(lock_path, timeout_sec=5.0, poll_sec=0.01)
assert fd is None
assert time.time() - started < 2.0
assert not lock_path.exists()
def test_a_stale_lock_is_never_evicted_without_the_kernel_hold(tmp_path, monkeypatch):
"""Eviction happens only under a held kernel lock on the judged fd: a
refusal of that hold that is not contention leaves the stale file where
it is and fails the acquisition closed — never unlink-by-name instead."""
lock_path = tmp_path / "state.lock"
lock_path.write_text("pid=424242 ts=0\n", encoding="utf-8")
os.utime(lock_path, (0.0, 0.0))
monkeypatch.setattr(platform_layer, "pid_is_alive", lambda pid: False)
_tier(monkeypatch, True)
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", _refusing(errno.EIO))
fd = acquire_exclusive_file_lock(
lock_path, timeout_sec=1.0, stale_sec=1.0, poll_sec=0.01, owner_aware_stale=True,
)
assert fd is None
assert lock_path.read_text(encoding="utf-8") == "pid=424242 ts=0\n"
def test_the_name_tier_is_chosen_by_the_predicate_not_by_a_refusal(tmp_path, monkeypatch):
"""Where the predicate says the filesystem takes no kernel locks, the name
protocol runs alone and NO kernel call is attempted — so a refusal can
never be what decides the tier. Abandoned locks are still reclaimed there
by the disclosed re-check-then-unlink shape."""
lock_path = tmp_path / "state.lock"
_tier(monkeypatch, False)
kernel_calls: list = []
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", kernel_calls.append)
fd = acquire_exclusive_file_lock(lock_path, metadata="pid=old ts=0\n")
assert fd is not None and kernel_calls == []
assert refresh_exclusive_file_lock(lock_path, fd) is True
release_exclusive_file_lock(lock_path, fd)
assert not lock_path.exists()
lock_path.write_text("pid=424242 ts=0\n", encoding="utf-8")
os.utime(lock_path, (0.0, 0.0))
monkeypatch.setattr(platform_layer, "pid_is_alive", lambda pid: False)
fd = acquire_exclusive_file_lock(
lock_path, timeout_sec=1.0, stale_sec=1.0, poll_sec=0.01, owner_aware_stale=True,
)
assert fd is not None and kernel_calls == []
release_exclusive_file_lock(lock_path, fd)
def test_the_capability_probe_decides_once_and_leaves_no_residue(tmp_path, monkeypatch):
"""Only the kernel's own "this filesystem cannot" answer selects the name
tier; any other refusal keeps the enforced tier (where a live acquisition
fails closed). The verdict is memoized per directory and the probe file
is gone afterwards."""
monkeypatch.setattr(platform_layer, "_KERNEL_LOCK_TIER", {})
assert platform_layer.kernel_file_locks_enforced(tmp_path / "real.lock") is True
lockless = tmp_path / "lockless"
lockless.mkdir()
answers: list = []
def probing(fd):
answers.append(fd)
raise OSError(errno.EOPNOTSUPP, "operation not supported")
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", probing)
assert platform_layer.kernel_file_locks_enforced(lockless / "a.lock") is False
assert platform_layer.kernel_file_locks_enforced(lockless / "b.lock") is False
assert len(answers) == 1 # one probe per directory
assert list(lockless.iterdir()) == []
# EIO is no capability answer: the enforced tier. ENOLCK — "no locks available",
# a lockd-less NFS or an exhausted lock table — is the name tier for ordinary
# locks, RECORDED beside the verdict so a caller may refuse it (the monetary lock does).
for code, enforced in ((errno.EIO, True), (errno.ENOLCK, False)):
refusing = tmp_path / f"refusing-{code}"
refusing.mkdir()
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", _refusing(code))
assert platform_layer.kernel_file_locks_enforced(refusing / "a.lock") is enforced, code
assert platform_layer._KERNEL_LOCK_TIER[os.path.realpath(str(refusing))] == (enforced, code)
assert list(refusing.iterdir()) == []
def test_enolck_is_the_name_tier_for_ordinary_locks_and_a_typed_refusal_for_money(tmp_path, monkeypatch):
"""A filesystem without a lock daemon answers ENOLCK to every kernel lock; so
does an exhausted lock table. Neither is "held", so the probe records it as the
name tier: ordinary locks (state singletons, task results, custody) keep the
O_EXCL name protocol they always ran there — the shared primitive fails no
one else closed — while the MONETARY lock names ENOLCK in
``refuse_name_tier_errnos`` and fails closed at once (no descriptor, no file,
the name protocol never run for money): every monetary writer refuses typed
and the compaction pass never enters on that tier."""
from ouroboros import usage_ledger
lock_path = tmp_path / "state" / "ordinary.lock"
lock_path.parent.mkdir() # an unprobeable (absent) directory answers enforced-uncached; probe the real one
monkeypatch.setattr(platform_layer, "_KERNEL_LOCK_TIER", {})
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", _refusing(errno.ENOLCK))
assert platform_layer.kernel_file_locks_enforced(lock_path) is False
fd = acquire_exclusive_file_lock(lock_path, timeout_sec=5.0, poll_sec=0.01)
assert fd is not None and lock_path.exists() # the name protocol, as before round 5.4
platform_layer.release_exclusive_file_lock(lock_path, fd)
started = time.time()
assert acquire_exclusive_file_lock(
lock_path, timeout_sec=5.0, poll_sec=0.01, refuse_name_tier_errnos=frozenset({errno.ENOLCK}),
) is None
assert time.time() - started < 2.0 and not lock_path.exists()
with pytest.raises(usage_ledger.UsageAccountingError, match="lock unavailable"):
with usage_ledger._named_lock(tmp_path, "usage_attempts.lock", timeout_sec=1.0, stale_sec=90.0):
raise AssertionError("the monetary lock was taken on the ENOLCK tier")
assert not (tmp_path / "state" / "usage_attempts.lock").exists()
def test_two_threads_racing_the_first_probe_run_one_probe_and_read_one_tier(tmp_path, monkeypatch):
"""The tier cache is read and written under one lock: two threads asking
about a directory nobody has probed run ONE probe and read one verdict —
never two probes whose answers could disagree (a lock-less answer on one,
a transient refusal on the other) and leave one thread on each tier of the
same directory, the compactor trusting a name-tier descriptor as enforced."""
monkeypatch.setattr(platform_layer, "_KERNEL_LOCK_TIER", {})
barrier = threading.Barrier(2)
probes: list = []
def probing(fd):
probes.append(fd)
with contextlib.suppress(threading.BrokenBarrierError):
barrier.wait(timeout=0.4) # two probes can only meet here without the cache lock
raise OSError(errno.EOPNOTSUPP, "operation not supported")
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", probing)
answers: list = [None, None]
def ask(slot):
answers[slot] = platform_layer.kernel_file_locks_enforced(tmp_path / "a.lock")
threads = [threading.Thread(target=ask, args=(slot,)) for slot in (0, 1)]
for thread in threads:
thread.start()
for thread in threads:
thread.join(timeout=10)
assert answers == [False, False] and len(probes) == 1
def test_lockfileex_refusals_classify_by_the_win32_error():
"""Only ERROR_LOCK_VIOLATION (33) means held by someone: it reads as the
busy errno and re-contends. Access denied (5) and sharing violation (32)
land on EACCES beside it on Windows, so EACCES cannot be in the busy set
(POSIX flock never answers it). ERROR_INVALID_FUNCTION (1) and
ERROR_NOT_SUPPORTED (50) — what a redirector answers when the volume takes
no byte-range locks at all — must reach the UNSUPPORTED set, or the name
tier is unreachable on Windows and a lock-less volume fails every monetary
append closed instead of degrading to the disclosed name protocol. Every
other error is in neither set: it fails the acquisition closed at once, not
after the timeout. The classified codes carry their errno themselves — the
4-argument OSError form derives errno FROM the winerror on Windows and
ignores the one passed, and answers 0 here — so this arithmetic is the same
on both platforms."""
assert errno.EACCES not in platform_layer._LOCK_HELD_ERRNOS
busy = platform_layer._win32_lock_error(33)
assert busy.errno in platform_layer._LOCK_HELD_ERRNOS and busy.winerror == 33
for err in (1, 50):
unsupported = platform_layer._win32_lock_error(err)
assert unsupported.errno in platform_layer._LOCK_UNSUPPORTED_ERRNOS and unsupported.winerror == err
for err in (5, 32, 6):
answered = platform_layer._win32_lock_error(err).errno
assert answered not in platform_layer._LOCK_HELD_ERRNOS
assert answered not in platform_layer._LOCK_UNSUPPORTED_ERRNOS
def test_the_design_note_names_the_exact_kernel_refusal_sets():
"""EACCES must not be described as contention: a genuine access-denied
would re-contend for the whole 45 s monetary timeout instead of failing
closed if the design note contradicted the implemented errno sets.
So the note names both sets and this compares them, member for member, by
the numbers (EWOULDBLOCK and ENOTSUP are aliases on Linux, not everywhere)."""
note = pathlib.Path(__file__).resolve().parents[1] / "docs" / "USAGE_COMPACTION.md"
spelled = re.findall(r"are exactly ((?:`[A-Z]+`/)+`[A-Z]+`)", note.read_text(encoding="utf-8"))
assert len(spelled) == 2, spelled
unsupported, held = ({getattr(errno, name.strip("`")) for name in group.split("/")} for group in spelled)
assert held == set(platform_layer._LOCK_HELD_ERRNOS)
assert unsupported == set(platform_layer._LOCK_UNSUPPORTED_ERRNOS)
@pytest.mark.skipif(
not platform_layer.IS_WINDOWS,
reason="LockFileEx error classification is Windows mechanics",
)
def test_windows_lockfileex_contention_reads_as_busy(tmp_path): # pragma: no cover - Windows only
"""A refused LockFileEx carries the errno the acquisition classifies: a
lock violation is contention (stand down, re-contend); anything else
fails closed. An errno-less OSError used to fall into the degrade."""
path = tmp_path / "held.lock"
first = os.open(str(path), os.O_CREAT | os.O_RDWR)
second = os.open(str(path), os.O_RDWR)
try:
platform_layer._win32_lock(first, exclusive=True, blocking=False)
with pytest.raises(OSError) as refused:
platform_layer._win32_lock(second, exclusive=True, blocking=False)
assert refused.value.errno in platform_layer._LOCK_HELD_ERRNOS
assert refused.value.winerror == 33 # ERROR_LOCK_VIOLATION
finally:
platform_layer._win32_unlock(first)
os.close(second)
os.close(first)
@pytest.mark.skipif(
platform_layer.IS_WINDOWS,
reason="the unlink-under-the-creator shape is POSIX; Windows cannot unlink an open file",
)
def test_a_lock_whose_identity_cannot_be_read_is_never_a_hold(tmp_path, monkeypatch):
"""``_lock_identity`` answers ``()`` for a descriptor it cannot ``fstat`` —
ESTALE/EIO on exactly the network filesystems this tier exists for. Two
unreadable sides are not a match: comparing them raw makes ``() == ()``
vacuously true and hands back a descriptor for an inode the path no longer
names (a reclaimer unlinked it inside its own re-contend window), i.e. a
second holder of one monetary lock. Unprovable is not owned: the
acquisition answers None — and the file it stamped with its own LIVE pid
goes with it, or no owner-aware reclaimer may ever remove it again."""
lock_path = tmp_path / "state.lock"
monkeypatch.setattr(platform_layer, "_KERNEL_LOCK_TIER", {})
assert platform_layer.kernel_file_locks_enforced(lock_path) is True # decided before the hooks
real_flock = platform_layer.file_lock_exclusive_nb
real_identity = platform_layer._lock_identity
def blind_descriptor(target): # our own fd answers nothing; the path still answers
return () if isinstance(target, int) else real_identity(target)
def evicting_flock(fd): # a reclaimer removed our file between the create and the lock
if lock_path.exists():
os.unlink(str(lock_path))
return real_flock(fd)
monkeypatch.setattr(platform_layer, "_lock_identity", blind_descriptor)
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", evicting_flock)
assert acquire_exclusive_file_lock(lock_path, timeout_sec=0.3, poll_sec=0.01) is None
monkeypatch.setattr(platform_layer, "file_lock_exclusive_nb", real_flock)
assert acquire_exclusive_file_lock(lock_path, timeout_sec=0.3, poll_sec=0.01) is None
assert not lock_path.exists(), "a live pid was stamped on a lock nobody may reclaim"
# The heartbeat has the same blind spots. A renewal is an ownership verdict:
# a renewal the kernel refuses is no renewal, our own identity unreadable
# with the path absent is not a match of two empty answers, and a stranger's
# file at the path is not ours either.
monkeypatch.setattr(platform_layer, "_lock_identity", real_identity)
fd = acquire_exclusive_file_lock(lock_path, timeout_sec=0.3, poll_sec=0.01)
assert fd is not None and refresh_exclusive_file_lock(lock_path, fd) is True
real_utime = os.utime
monkeypatch.setattr(os, "utime", lambda *a, **k: (_ for _ in ()).throw(OSError(errno.EIO, "utime refused")))
assert refresh_exclusive_file_lock(lock_path, fd) is False
monkeypatch.setattr(os, "utime", real_utime)
monkeypatch.setattr(platform_layer, "_lock_identity", blind_descriptor)
os.unlink(str(lock_path))
assert refresh_exclusive_file_lock(lock_path, fd) is False
lock_path.write_text("pid=1 ts=stranger\n", encoding="utf-8")
assert refresh_exclusive_file_lock(lock_path, fd) is False
os.close(fd)
def test_pid_is_signalable_is_the_kill_question():
"""Liveness and ownership are different questions: a pid another user owns
(pid 1 on a non-root POSIX host) is ALIVE for a lock owner but NOT signalable,
so a cleanup must not try to kill it; our own pid is both; a vanished pid is neither."""
assert platform_layer.pid_is_signalable(os.getpid()) is True
assert platform_layer.pid_is_signalable(0) is False
if not platform_layer.IS_WINDOWS and getattr(os, "geteuid", lambda: 1)() != 0:
assert platform_layer.pid_is_alive(1) is True
assert platform_layer.pid_is_signalable(1) is False
def _windows_kernel_tier(monkeypatch):
"""Drive the WINDOWS lock shapes on any host: ``IS_WINDOWS`` plus a stand-in for the
two LockFileEx wrappers (whose ``ctypes.wintypes`` exists on Windows only). The
stand-in grants exactly what the real one asks the kernel for — an exclusive hold on
the single byte at ``_WIN32_LOCK_OFFSET``, refused with ERROR_LOCK_VIOLATION while
another descriptor holds it — and RECORDS every range requested, so a pin can compare
it against the stamp bytes a contender must still be able to read. Returns that log."""
monkeypatch.setattr(platform_layer, "IS_WINDOWS", True)
monkeypatch.setattr(platform_layer, "_KERNEL_LOCK_TIER", {})
ranges: list = []
held: dict = {}
def win32_lock(fd, *, exclusive=True, blocking=True):
ranges.append((platform_layer._WIN32_LOCK_OFFSET, platform_layer._WIN32_LOCK_LENGTH))
info = os.fstat(fd)
if held.get((info.st_dev, info.st_ino), fd) != fd:
raise platform_layer._win32_lock_error(33) # ERROR_LOCK_VIOLATION: held by someone
held[(info.st_dev, info.st_ino)] = fd
def win32_unlock(fd):
for key, owner in list(held.items()):
if owner == fd:
del held[key]
monkeypatch.setattr(platform_layer, "_win32_lock", win32_lock)
monkeypatch.setattr(platform_layer, "_win32_unlock", win32_unlock)
return ranges
def test_the_windows_lock_range_lies_beyond_every_owner_stamp():
"""The bf8b6549 matrix died of a MANDATORY whole-file LockFileEx: a contender
could not READ the stamp it must read to judge the hold, so every wait ran to
its timeout (eight monetary writers refused, a chat append lost). The hold is
therefore one byte at an offset the stamp — one short line, read 512 bytes at a
time — can never reach, and the whole-file range is gone from both wrappers."""
assert platform_layer._WIN32_LOCK_LENGTH == 1
assert platform_layer._WIN32_LOCK_OFFSET > 512 * 1024 ** 3 # unreachable by any lock file
for wrapper in (platform_layer._win32_lock, platform_layer._win32_unlock):
source = inspect.getsource(wrapper)
assert "_WIN32_LOCK_OFFSET" in source and "_WIN32_LOCK_LENGTH" in source
assert "0xFFFFFFFF, 0xFFFFFFFF" not in source, "the whole-file range is back"
def test_windows_contenders_read_the_owner_stamp_while_the_kernel_hold_stands(tmp_path, monkeypatch):
"""With the range beyond the stamp the Windows tier behaves like POSIX: the
predicate answers enforced, the hold is real (a second acquirer is refused), and
the contender still READS the owner stamp on every poll — so it judges a live
hold and stands down instead of timing out blind, which is what makes the tier
shippable at all. The stamp bytes are never inside a requested range."""
ranges = _windows_kernel_tier(monkeypatch)
lock_path = tmp_path / "state.lock"
assert platform_layer.kernel_file_locks_enforced(lock_path) is True
fd = acquire_exclusive_file_lock(lock_path, timeout_sec=1.0, poll_sec=0.01)
assert fd is not None
with open(str(lock_path), "rb") as contender: # the read a mandatory hold refused
assert f"pid={os.getpid()}".encode() in contender.read(512)
assert acquire_exclusive_file_lock(lock_path, timeout_sec=0.3, poll_sec=0.01) is None
assert ranges and all(offset >= 512 for offset, _length in ranges)
release_exclusive_file_lock(lock_path, fd)
assert not lock_path.exists()
again = acquire_exclusive_file_lock(lock_path, timeout_sec=0.5, poll_sec=0.01)
assert again is not None
release_exclusive_file_lock(lock_path, again)
def test_windows_evicts_a_stale_lock_only_under_the_probe_hold(tmp_path, monkeypatch):
"""On the enforced tier Windows now takes the SAME kernel hold on the judged
descriptor before it may evict — it just unlinks after closing the probe,
because it deletes no open file. A stale-looking lock somebody actually holds
is therefore never evicted (the hold refuses the probe); an abandoned one is."""
_windows_kernel_tier(monkeypatch)
monkeypatch.setattr(platform_layer, "pid_is_alive", lambda pid: False)
lock_path = tmp_path / "state.lock"
lock_path.write_text("pid=424242 ts=0\n", encoding="utf-8")
os.utime(lock_path, (0.0, 0.0)) # ancient: judged abandoned by age
holder = os.open(str(lock_path), os.O_RDWR)
platform_layer.file_lock_exclusive_nb(holder) # ... but a live kernel hold stands
assert acquire_exclusive_file_lock(
lock_path, timeout_sec=0.4, stale_sec=1.0, poll_sec=0.01, owner_aware_stale=True,
) is None
assert lock_path.read_text(encoding="utf-8") == "pid=424242 ts=0\n"
platform_layer.file_unlock(holder)
os.close(holder)
reclaimed = acquire_exclusive_file_lock(
lock_path, timeout_sec=1.0, stale_sec=1.0, poll_sec=0.01, owner_aware_stale=True,
)
assert reclaimed is not None
release_exclusive_file_lock(lock_path, reclaimed)
def test_windows_release_unlocks_before_the_close_and_unlinks_after_it(tmp_path, monkeypatch):
"""Order, on Windows: release the kernel hold (a handle closed with an
outstanding lock leaves the release undefined), then close, then unlink — the
file being undeletable while our own handle is open. Read by the fd's own
liveness: it must still be open at the unlock and gone by the unlink."""
_windows_kernel_tier(monkeypatch)
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path, timeout_sec=1.0, poll_sec=0.01)
assert fd is not None
order: list = []
real_unlock, real_unlink = platform_layer.file_unlock, platform_layer._unlink_lock_path
def unlock(target):
order.append(("unlock", _fd_open(target)))
return real_unlock(target)
def unlink(path, held):
order.append(("unlink", _fd_open(fd)))
return real_unlink(path, held)
monkeypatch.setattr(platform_layer, "file_unlock", unlock)
monkeypatch.setattr(platform_layer, "_unlink_lock_path", unlink)
release_exclusive_file_lock(lock_path, fd)
assert order == [("unlock", True), ("unlink", False)]
assert not lock_path.exists()
def _fd_open(fd):
try:
os.fstat(fd)
except OSError:
return False
return True
def _refusing_unlink(monkeypatch, lock_path, *, refusals):
"""Windows delete semantics on any host: ``os.unlink`` of ``lock_path`` answers
a sharing violation ``refusals`` times (a contender's probe handle still open —
``None``: forever), then behaves. Returns the attempt counter."""
real_unlink, attempts = os.unlink, []
def unlink(path, *args, **kwargs):
if pathlib.Path(path) == lock_path:
attempts.append(time.monotonic())
if refusals is None or len(attempts) <= refusals:
raise PermissionError(errno.EACCES, "[WinError 32] sharing violation", str(path))
return real_unlink(path, *args, **kwargs)
monkeypatch.setattr(platform_layer.os, "unlink", unlink)
return attempts
def test_windows_release_retries_a_contenders_transient_sharing_refusal(tmp_path, monkeypatch):
"""The name protocol's contenders open the lock on every poll; on Windows that
handle makes the owner's unlink fail with a sharing violation for a moment.
Swallowing it orphaned the lock with the owner's LIVE pid inside (the Windows
matrices after the C6 merge: every later monetary writer refused, chat appends
fell to the unlocked lane), so the release retries until the handle is gone
and the next acquirer wins at once instead of waiting out its timeout."""
_windows_kernel_tier(monkeypatch)
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path)
assert fd is not None
attempts = _refusing_unlink(monkeypatch, lock_path, refusals=3)
release_exclusive_file_lock(lock_path, fd)
assert len(attempts) == 4 and not lock_path.exists()
fd2 = acquire_exclusive_file_lock(lock_path, timeout_sec=0.2, owner_aware_stale=True)
assert fd2 is not None
release_exclusive_file_lock(lock_path, fd2)
assert not lock_path.exists()
def test_windows_release_gives_up_a_refusal_that_never_clears(tmp_path, monkeypatch):
"""The retry is bounded: a handle that never closes (an indexer, a foreign
reader) cannot pin the releasing writer forever — it logs and returns
within the window, leaving the file it could not remove."""
_windows_kernel_tier(monkeypatch)
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path)
assert fd is not None
attempts = _refusing_unlink(monkeypatch, lock_path, refusals=None)
started = time.monotonic()
release_exclusive_file_lock(lock_path, fd)
assert 1.5 < time.monotonic() - started < 6.0 and len(attempts) > 10
assert lock_path.exists()
@pytest.mark.skipif(platform_layer.IS_WINDOWS, reason="POSIX release order under test: with IS_WINDOWS patched False the enforced-tier probe imports fcntl, which Windows lacks")
def test_posix_release_does_not_retry_a_permission_refusal(tmp_path, monkeypatch):
"""POSIX never refuses an unlink for a reader's open handle: a
PermissionError there is the directory's mode, permanent — retrying would
only delay the writer by the whole window."""
monkeypatch.setattr(platform_layer, "IS_WINDOWS", False)
lock_path = tmp_path / "state.lock"
fd = acquire_exclusive_file_lock(lock_path)
assert fd is not None
attempts = _refusing_unlink(monkeypatch, lock_path, refusals=None)
release_exclusive_file_lock(lock_path, fd)
assert len(attempts) == 1 and lock_path.exists()
monkeypatch.undo() # 3.11+ pathlib.unlink calls os.unlink live: the refuser must be gone first
lock_path.unlink()
# --------------------------------------------------------------------------- #
# Shared sidecar locks: one file, one staleness contract
# --------------------------------------------------------------------------- #
def _live_holders_aged_lock(lock_path: pathlib.Path) -> tuple:
"""A lock file stamped with a LIVE owner (this process) and back-dated far
past every stale window the sidecar takers use. Age alone must not make it
evictable: the owner is alive and still inside its critical section."""
lock_path.parent.mkdir(parents=True, exist_ok=True)
lock_path.write_text(f"pid={os.getpid()} ts=0\n", encoding="utf-8")
aged = time.time() - 600.0
os.utime(lock_path, (aged, aged))
return platform_layer._lock_identity(lock_path)
def _custody_ledger_rewrite(drive: pathlib.Path):
"""process_custody._rewrite_ledger -- same sidecar as append_jsonl(ledger)."""
from ouroboros import process_custody
from ouroboros.utils import jsonl_append_lock_path
path = process_custody.ledger_path(drive)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text('{"pid": 4242, "event": "START_REQUESTED"}\n', encoding="utf-8")
return path, jsonl_append_lock_path(path), lambda: process_custody._rewrite_ledger(drive, [])
def _skill_review_history_append(drive: pathlib.Path):
"""skill_review_history.append_history_once -- same sidecar as its own
append_jsonl writer of the very same history file."""
from ouroboros import skill_review_history
from ouroboros.utils import jsonl_append_lock_path
path = skill_review_history.review_history_path(drive, "demo")
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(b"")
return path, jsonl_append_lock_path(path), lambda: skill_review_history.append_history_once(
drive, "demo", {"job_id": "job-1", "ts": "2026-01-01T00:00:00Z"},
)
def _supervisor_log_rotation(drive: pathlib.Path):
"""supervisor.state.rotate_jsonl_log_if_needed -- renames a log whose rows
append_jsonl writes under this same lock."""
from ouroboros.utils import jsonl_append_lock_path
from supervisor import state as supervisor_state
path = drive / "logs" / "chat.jsonl"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text('{"role": "user"}\n', encoding="utf-8")
return path, jsonl_append_lock_path(path), lambda: supervisor_state.rotate_jsonl_log_if_needed(
drive, "chat.jsonl", "chat", max_bytes=8,
)
def _durable_json_update(drive: pathlib.Path):
"""utils.update_json_locked -- the <file>.lock sidecar that cancel-intent
projection and task-result quarantine take on the very same files."""
from ouroboros.utils import update_json_locked
path = drive / "state" / "durable.json"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text('{"generation": 1}\n', encoding="utf-8")
return path, path.with_name(path.name + ".lock"), lambda: update_json_locked(
path, lambda current: {"generation": 2}, timeout_sec=0.3,
)
@pytest.mark.parametrize("build", [
_custody_ledger_rewrite,
_skill_review_history_append,
_supervisor_log_rotation,
_durable_json_update,
], ids=["process_custody", "skill_review_history", "supervisor_rotation", "update_json_locked"])
def test_a_shared_sidecar_taker_never_evicts_a_live_holders_lock(tmp_path, monkeypatch, build):
"""Every writer of one lock file must judge staleness the same way.
An age-only taker unlinks a LIVE holder's lock and then enters a critical
section the holder believes it owns -- the Windows `results=[True, True]`
class from the observation inbox, one lock file per authority. Pinned on
the NAME tier, where nothing but the staleness contract stands between the
contender and the eviction.
"""
monkeypatch.setattr(platform_layer, "kernel_file_locks_enforced", lambda _path: False)
target, lock_path, invoke = build(tmp_path)
before = target.read_bytes()
identity = _live_holders_aged_lock(lock_path)
with contextlib.suppress(TimeoutError):
invoke() # the contender: it must wait the holder out, never evict it
assert platform_layer._lock_identity(lock_path) == identity, "the live holder's lock was evicted"
assert target.read_bytes() == before, "a second writer entered the holder's critical section"