From f159ca7d275158ba3f93b082f093f5cb9d6c1cf3 Mon Sep 17 00:00:00 2001 From: Dai Ha Date: Fri, 4 Sep 2026 13:22:55 +0700 Subject: [PATCH] #310: log when a reap is skipped because the record changed The compare-and-release declines silently. This race is unobservable by construction, so a reaper that quietly stops reaping is the hardest kind of behaviour to diagnose later. One debug line names the pane and the likely cause. --- .../src/main/java/dev/ltms/fleet/session/SessionManager.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fleetd/src/main/java/dev/ltms/fleet/session/SessionManager.java b/fleetd/src/main/java/dev/ltms/fleet/session/SessionManager.java index cf8d8d5..9c093c0 100644 --- a/fleetd/src/main/java/dev/ltms/fleet/session/SessionManager.java +++ b/fleetd/src/main/java/dev/ltms/fleet/session/SessionManager.java @@ -294,6 +294,11 @@ public final class SessionManager implements TurnListener { */ private boolean releaseIfCurrent(MemberSession expected, ReleaseCause cause) { if (!registry.remove(expected.paneId(), expected)) { + // A lifecycle transition replaced the record between the caller's check and this remove. + // Log it: this race is by definition unobservable otherwise, and a reaper that silently + // declines to reap is the hardest kind of behaviour to diagnose after the fact. + log.debug("skipping reap of pane={}: its registry record changed after the idle check " + + "(most likely a delivery made it BUSY)", expected.paneId()); return false; } releaseRemoved(expected.paneId(), expected, handles.remove(expected.paneId()), cause);