fleetd #572: pin answer()'s session-lock release across all four exits #574
Reference in New Issue
Block a user
Delete Branch "worker/572-answer-lock-release-46a9ae-5"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes fleetd #572.
MessageService.answer() releases its per-session lock in an outer finally (MessageService.java:1218). Mutation testing on main at
ba2f4d1showed this line is covered-but-unasserted: removing it leaves all 1750 existing tests green, because every existing test on this path checks answer()'s return value, never that the lock it took is actually reacquirable afterward. If the lock leaks, the session is wedged forever with no exception and no log line.Adds four tests (no production change) to MessageServiceTest, one per exit of answer(): normal REPLIED reply, TIMED_OUT_WORKING, ExecutionException rethrow, InterruptedException rethrow. Each proves the lock is reacquirable via a bounded (300ms) follow-up send on the same session, rather than only checking answer()'s own outcome.
Verification performed:
grep -Fxc ' lock.unlock();'= 2 (pristine).sed -i '' '1218s|.*| /* mutation L: unlock removed */|') -> anchor count drops to 1, sha256 changes. Re-ran MessageServiceTest: all four new tests fail RED naming themselves (answerReleasesTheSessionLockAfterANormalReply, answerReleasesTheSessionLockAfterATimedOutWorkingReturn, answerReleasesTheSessionLockWhenTheReplyFutureFailsExceptionally, answerReleasesTheSessionLockWhenInterrupted), all 83 other MessageServiceTest tests stay green (87 total, 4 failures, 0 errors).git checkout: sha256 and anchor count back to pristine (2), git status clean on the production file.Shape note (not fixed, per ticket instructions): the same shared 2-line cleanup (asyncTasksByWaiter.remove + rendezvous.close) is duplicated at three sites in MessageService.java -- around lines 994-995 (send()'s finally), 1134-1135 (answer()'s inline STALE_TURN early-return cleanup), and 1214-1215 (answer()'s inner finally) -- the same maintained-at-N-sites shape as the lock.unlock() finding. Not investigated further, per scope.