Skip to content

fix: stop retrying on local socket exhaustion - #3062

Open
nakamotoliu wants to merge 1 commit into
MetaCubeX:Alphafrom
nakamotoliu:fix/stop-retry-local-resource-exhaustion
Open

fix: stop retrying on local socket exhaustion#3062
nakamotoliu wants to merge 1 commit into
MetaCubeX:Alphafrom
nakamotoliu:fix/stop-retry-local-resource-exhaustion

Conversation

@nakamotoliu

Copy link
Copy Markdown

Summary

Stop the tunnel dial retry loop immediately when the local host reports socket resource exhaustion, including EADDRNOTAVAIL.

Root cause

tunnel.retry currently attempts most failed dials up to 10 times. Local resource exhaustion is not transient on the retry loop's millisecond-to-second time scale. Retrying EADDRNOTAVAIL, EMFILE, ENFILE, or ENOBUFS cannot free the exhausted resource and may amplify an existing connection storm.

In one macOS TUN incident, the IPv4 ephemeral port range contained 16,384 ports while the host had approximately 16,477 TCP sockets in TIME_WAIT. IPv4 loopback connections then failed with errno 49 / EADDRNOTAVAIL, even though the local services were still listening. Multiple rule providers and health checks continued dialing through the same retry path.

Changes

  • classify local socket resource exhaustion as non-retryable by the fast dial retry loop;
  • use the native WinSock/Win32 equivalents on Windows;
  • preserve the existing behavior for ordinary transient network errors;
  • add tests for direct and wrapped syscall errors and attempt counts.

Impact

This does not attempt to repair an already exhausted OS socket table. It prevents Mihomo from multiplying each failed dial into up to 10 attempts, reducing the chance that a degraded network state escalates into complete local IPv4 connection failure.

Validation

  • go vet ./tunnel
  • go test ./tunnel -count=1
  • GOTOOLCHAIN=go1.20.14 go test ./tunnel -count=1
  • SKIP_INTEROP_TEST=1 go test ./... -count=1
  • SKIP_INTEROP_TEST=1 go test ./... -tags with_gvisor -count=1
  • compiled the tunnel test binary for Darwin/arm64, Linux/amd64, and Windows/amd64
  • compiled the Windows/amd64 tunnel test binary with Go 1.20.14

Related downstream report: clash-verge-rev/clash-verge-rev#7532

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant