You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Runtime Host PID-known retirement can stop a successor and report the old epoch as retired #3594
Follow-up to #3557, which is already merged (7f68af7655e5bbc74e70f531dea1acfca2e93dc9). This was recorded as a non-blocking [P3] during review and deliberately not treated as a merge hold; opening it so it does not get lost.
The gap
In the PID-known retirement path, packages/cli/src/runtime-host-service-manager.ts:380-417, the old Host is prepared and then backend.stop() is called without holding a State Root fence. Only the service.state === 'starting' branch assigns a rootFence.
If the old process exits abnormally in that window and systemd starts a successor, backend.stop() can stop the successor while the command then reports retirement using the old epoch and PID. The caller is told the host it named was retired; what actually happened is that a different, newer host was stopped.
The post-stop checks do not close this. verifyRuntimeHostRootReleased(root) and the stopped.active/state/pid inspection prove that no writer holds the root at that moment — they cannot prove an identity-continuous handoff, because the identity being asked about may already have been replaced.
Why the obvious fix is not enough
Re-reading identity after stop is too late: by then the successor has already been stopped and any writes it made in the window are unrecoverable. The correct shape is to hold the fence across the stop, or to model retirement as an explicit transition that fails when the observed identity is not the one that was prepared.
Acceptance criteria
A crash → restart interleaving test: prepare against a known PID, kill that process abnormally inside the window, let a successor come up, and assert the command does not stop the successor and does not report retirement of the old epoch/PID as success.
The State Root fence is held across backend.stop() on the PID-known path, not only on the starting path — or retirement is expressed as an explicit transition that rejects an identity mismatch.
The post-stop root-vacancy check is documented for what it actually proves (no current writer) rather than as evidence of a continuous handoff.
Severity
P3 as rated: the window is narrow, there is no concurrent writer, and no direct data corruption was demonstrated. It is a correctness gap in what the command claims happened, which is why it is worth fixing rather than shipping as understood behaviour.
Provenance
Found during #3557 review, with the fix direction corrected in a review addendum (5002040661) after the first proposed fix — a post-stop identity re-read — was shown to be too late. A second reviewer independently reproduced the same window afterwards and labelled it corroboration rather than an independent finding.
Hi, I'd like to work on this issue.
My plan is to hold the State Root retirement fence across backend.stop() on the PID-known path, add a deterministic crash → restart interleaving regression test that verifies the successor is neither stopped nor misreported as the retired Host, and clarify what the post-stop root-vacancy check proves.
Could you please assign this issue to me?
Hi, I'd like to work on this issue.嗨,我希望能参与这个项目的开发工作。 My plan is to hold the State Root retirement fence across backend.stop() on the PID-known path, add a deterministic crash → restart interleaving regression test that verifies the successor is neither stopped nor misreported as the retired Host, and clarify what the post-stop root-vacancy check proves.我的计划是在 PID 已知路径上的 backend.stop() 处设置状态根节点退役测试点,然后添加一个确定性的崩溃测试——重新执行验证后续节点的测试,确保后续节点既没有被停止,也不会被错误地报告为已退役的节点。同时,还需要明确在节点退役后进行的根节点空缺检查究竟能证明什么。 Could you please assign this issue to me?请能否将这个问题交给我处理?
Hi @Sun-GLiang, I saw your comment and noticed that our approaches overlap. I have independently implemented the Runtime Host retirement fence and added deterministic regression tests for the successor race.
I don't want to duplicate your work. Would you prefer to coordinate on one implementation, or should I open my branch as a PR for maintainer review?
I noticed that #3594 is assigned to @Sun-GLiang. I opened #3602 before
realizing that the issue had already been assigned.
Since #3602 already contains the implementation and regression tests, would
you be open to collaborating on this fix? I’m happy to coordinate with @Sun-GLiang on the remaining validation and review, if that works for everyone.
I don’t want to duplicate anyone’s work, so please let me know how you would
prefer to proceed.
Hi @Astro-Han, thank you for assigning #3594 to me.
I noticed that @CuSO41108 opened #3602 while I was working on the issue independently. I’m happy to collaborate with them, and I’m currently reviewing #3602 against the issue’s acceptance criteria and the relevant retirement lifecycle edge cases.
I have also completed a local implementation with deterministic regression coverage for the successor race, asynchronous Host drain, stable-stopped transition, and fence cleanup failures. I can share the relevant findings, tests, or focused patches with @CuSO41108 so that we can converge on a single implementation.
To avoid competing PRs, I won’t open another PR while this coordination is ongoing. Please let us know if you would prefer a different workflow.
Hi @CuSO41108, thanks for clarifying. I agree that this was parallel work, and I appreciate your willingness to coordinate.
I’m not a maintainer and I don’t have write access to either your fork branch or the upstream repository, so I’m not in a position to decide which implementation should be merged.
I had already started working after asking to claim #3594, and I have now completed an independent implementation and local verification. I also reviewed the current head of #3602 as a peer contributor. The core fencing direction is aligned, although I found a few lifecycle, scope, and test-coverage differences that I think are worth discussing.
To avoid creating competing PRs, I’ll leave the technical findings as comments on #3602 and can share my branch and the relevant tests or patches for you to incorporate. I won’t open another PR unless the maintainers ask for one. @Astro-Han, could you please advise whether you would prefer us to continue by improving #3602 together, or whether you would like to compare the alternative implementation before choosing a path?
OK, it seems like two of us has overlapped on this issue. Glad we could work together on this issue, maybe we could focus on solving #3602 and @Sun-GLiang could help @CuSO41108 with code reviews? Thanks to both of you~
Thanks for coordinating this. I really appreciate the guidance and Sun’s
willingness to review the work.
I’ll continue the implementation and discussion in #3602 for now. @Sun-GLiang,
please feel free to share the lifecycle, scope, and test-coverage findings,
along with any focused tests or patches. I’ll review them against the issue’s
acceptance criteria, and we can discuss any necessary updates there.
Activity
Sun-GLiang commentedon Aug 23, 2026
Hi, I'd like to work on this issue.
My plan is to hold the State Root retirement fence across
backend.stop()on the PID-known path, add a deterministic crash → restart interleaving regression test that verifies the successor is neither stopped nor misreported as the retired Host, and clarify what the post-stop root-vacancy check proves.Could you please assign this issue to me?
CuSO41108 commentedon Aug 23, 2026
Hi @Sun-GLiang, I saw your comment and noticed that our approaches overlap. I have independently implemented the Runtime Host retirement fence and added deterministic regression tests for the successor race.
I don't want to duplicate your work. Would you prefer to coordinate on one implementation, or should I open my branch as a PR for maintainer review?
CuSO41108 commentedon Aug 23, 2026
Hi @Sun-GLiang @Astro-Han,
I noticed that #3594 is assigned to @Sun-GLiang. I opened #3602 before
realizing that the issue had already been assigned.
Since #3602 already contains the implementation and regression tests, would
you be open to collaborating on this fix? I’m happy to coordinate with
@Sun-GLiang on the remaining validation and review, if that works for everyone.
I don’t want to duplicate anyone’s work, so please let me know how you would
prefer to proceed.
Sun-GLiang commentedon Aug 23, 2026
Hi @Astro-Han, thank you for assigning #3594 to me.
I noticed that @CuSO41108 opened #3602 while I was working on the issue independently. I’m happy to collaborate with them, and I’m currently reviewing #3602 against the issue’s acceptance criteria and the relevant retirement lifecycle edge cases.
I have also completed a local implementation with deterministic regression coverage for the successor race, asynchronous Host drain, stable-stopped transition, and fence cleanup failures. I can share the relevant findings, tests, or focused patches with @CuSO41108 so that we can converge on a single implementation.
To avoid competing PRs, I won’t open another PR while this coordination is ongoing. Please let us know if you would prefer a different workflow.
Sun-GLiang commentedon Aug 23, 2026
Hi @CuSO41108, thanks for clarifying. I agree that this was parallel work, and I appreciate your willingness to coordinate.
I’m not a maintainer and I don’t have write access to either your fork branch or the upstream repository, so I’m not in a position to decide which implementation should be merged.
I had already started working after asking to claim #3594, and I have now completed an independent implementation and local verification. I also reviewed the current head of #3602 as a peer contributor. The core fencing direction is aligned, although I found a few lifecycle, scope, and test-coverage differences that I think are worth discussing.
To avoid creating competing PRs, I’ll leave the technical findings as comments on #3602 and can share my branch and the relevant tests or patches for you to incorporate. I won’t open another PR unless the maintainers ask for one.
@Astro-Han, could you please advise whether you would prefer us to continue by improving #3602 together, or whether you would like to compare the alternative implementation before choosing a path?
Astro-Han commentedon Aug 23, 2026
OK, it seems like two of us has overlapped on this issue. Glad we could work together on this issue, maybe we could focus on solving #3602 and @Sun-GLiang could help @CuSO41108 with code reviews? Thanks to both of you~
CuSO41108 commentedon Aug 23, 2026
Hi @Astro-Han and @Sun-GLiang,
Thanks for coordinating this. I really appreciate the guidance and Sun’s
willingness to review the work.
I’ll continue the implementation and discussion in #3602 for now. @Sun-GLiang,
please feel free to share the lifecycle, scope, and test-coverage findings,
along with any focused tests or patches. I’ll review them against the issue’s
acceptance criteria, and we can discuss any necessary updates there.
Thanks again!