fix(id_order): a dead-owner marker on the caller's own session follows the orphan rules (Issue #63)
A marker left on the invoking session name by a killed create/resume was pruned before herdr was asked, so a retry under the same name took it over while the orphaned pane was still alive (and create's failure cleanup could then kill it). It is now kept and blocks like any other orphan until its row is registered for the attempt or herdr reports the session gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7cac6f613e
commit
1614af5b67
2 files changed
+42
-16
No files matched your search
@@ -180,15 +180,16 @@ def _registered_for_attempt(m: Dict[str, Any], row: Optional[Dict[str, Any]]) ->
|
||||
return int(row.get("herdr_session_epoch") or 0) > int(m.get("prev_epoch") or 0)
|
||||
|
||||
|
||||
def _read_and_prune_markers(dpath: str, me: str, my_pid: int, state: Dict[str, Any],
|
||||
def _read_and_prune_markers(dpath: str, my_pid: int, state: Dict[str, Any],
|
||||
is_alive: Callable[[int], bool] = pid_alive,
|
||||
pane_state: Callable[[str, str], Optional[bool]] = (
|
||||
lambda server, session: None),
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Markers that still count. A live owner keeps its marker (another live
|
||||
attempt on `me` included). A dead owner's marker goes once its row is
|
||||
registered for the attempt (the row decides from then on) or herdr answers
|
||||
that its session is gone; until then it is kept as an orphan."""
|
||||
attempt on the caller's session included). A dead owner's marker goes once
|
||||
its row is registered for the attempt (the row decides from then on) or
|
||||
herdr answers that its session is gone; until then it is kept as an orphan,
|
||||
one an earlier attempt left on the caller's session included."""
|
||||
rows_by_name = {
|
||||
str(s.get("name") or ""): s
|
||||
for s in (state.get("herdr_sessions") or []) if isinstance(s, dict)
|
||||
@@ -219,7 +220,7 @@ def _read_and_prune_markers(dpath: str, me: str, my_pid: int, state: Dict[str, A
|
||||
drop = True
|
||||
elif is_alive(owner_pid):
|
||||
drop = False
|
||||
elif sess == me or not sess:
|
||||
elif not sess:
|
||||
drop = True
|
||||
elif _registered_for_attempt(data, rows_by_name.get(sess)):
|
||||
drop = True
|
||||
@@ -304,7 +305,7 @@ def wait(cwd: str, agent: str, session: str, owner_pid: int,
|
||||
file=sys.stderr, flush=True,
|
||||
)
|
||||
return 1
|
||||
markers = _read_and_prune_markers(dpath, session, owner_pid, state,
|
||||
markers = _read_and_prune_markers(dpath, owner_pid, state,
|
||||
is_alive=is_alive, pane_state=bounded_probe)
|
||||
blks = blockers(state, cwd, agent, session, markers, is_alive=is_alive)
|
||||
if not blks:
|
||||
|
||||
Reference in new issue
Block a user