fix(cli): route isPortBusy through checkPortInUse to detect IPv4-only occupants#94456
fix(cli): route isPortBusy through checkPortInUse to detect IPv4-only occupants#94456Pandah97 wants to merge 3 commits into
Conversation
… occupants - Export checkPortInUse from src/infra/ports-inspect.ts - Replace bare tryListenOnPort in isPortBusy with checkPortInUse which probes all four endpoints (127.0.0.1, 0.0.0.0, ::1, ::) - Previously a host-less listen only bound to IPv6 wildcard (::), missing IPv4-only 127.0.0.1 occupants on dual-stack machines Fixes openclaw#94426
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. Close: this useful CLI bug-fix branch is now superseded by the focused, proof-positive sibling at #94949, while this PR duplicates the current main probe helper shape and carries unrelated agent/provider cherry-pick files. Canonical path: Land the focused sibling #94949 as the canonical fix, then close this duplicate branch and the linked issue after that PR merges. So I’m closing this here and keeping the remaining discussion on #94949. Review detailsBest possible solution: Land the focused sibling #94949 as the canonical fix, then close this duplicate branch and the linked issue after that PR merges. Do we have a high-confidence way to reproduce the issue? Yes. Current main still uses a hostless Is this the best way to solve the issue? No for this branch as the landing path. Reusing a shared multi-endpoint probe is the right fix, but current main's owner is now Security review: Security review cleared: The diff adds no dependency, workflow, secret, permission, package, or supply-chain surface; the security pass found no concrete concern. AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model internal, reasoning high; reviewed against 6834a2d47bbf. |
Cherry-pick from main to fix pre-existing test failure in openai-transport-stream where tools are expected to have strict:true but code on this branch produces strict:false.
CI fixesFixed 2 of 4 failing CI checks:
Remaining failures ( |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
ClawSweeper applied the proposed close for this PR.
|
Summary
isPortBusy()insrc/cli/ports.ts(thegateway --forcekill-port guard) uses a baretryListenOnPort({ port, exclusive: true })which binds to the IPv6 wildcard (::) on dual-stack machines. An IPv4-only occupant listening on127.0.0.1does not conflict with that bind, soisPortBusyreports the port as free when it is actually taken.Root cause: Same address-family flaw as #94379. A host-less
net.listenbinds::on dual-stack kernels (net.ipv6.bindv6only=0), missing IPv4-only listeners.Fix: Route
isPortBusythroughcheckPortInUse()(exported fromsrc/infra/ports-inspect.ts) which probes all four endpoints —127.0.0.1,0.0.0.0,::1,::— instead of a single bare listen. Map its"busy"result totrue.Fixes #94426
Real behavior proof (required for external PRs)
Behavior addressed:
isPortBusy()now detects IPv4-only127.0.0.1port occupants on dual-stack machines.Real setup tested:
416e2c9432checkPortInUse()function fromsrc/infra/ports-inspect.tsviatsx(TypeScript runtime), created a real IPv4-onlynet.Serverlistening on127.0.0.1, and verified the probe correctly returns"busy". Also verified that free ports return"free".Exact steps or command run after fix:
After-fix evidence:
Before/after comparison:
::which does not conflict with127.0.0.1What was not tested: Exhaustive matrix of all possible port states. The three outcomes (
"free","busy","unknown") are exercised by the existing unit test suite (23 tests across 3 files). The live socket test above covers the specific bug scenario: an IPv4-only127.0.0.1listener that the old hostless bind would miss.Tests and validation
All 23 port-related tests pass across 3 test files. Additionally verified with a live IPv4-only
127.0.0.1socket that the probe correctly returns"busy".Risk checklist
Did user-visible behavior change? (
Yes)gateway --forcenow correctly detects IPv4-only port occupants instead of missing themDid config, environment, or migration behavior change? (
No)Did security, auth, secrets, network, or tool execution behavior change? (
No)What is the highest-risk area?
checkPortInUsereturns"unknown"when all four probes fail with non-EADDRINUSE errors (edge case);isPortBusythrows for this case, same as the old code threw for non-EADDRINUSE errorsHow is that risk mitigated?
checkPortInUsefunction was already thoroughly tested in fix(ports): probe all address families in ensurePortAvailable #94415 (13 tests)Current review state
What is the next action?
Which bot or reviewer comments were addressed?