Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions docsforge/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,7 @@ def _find_available_port(host: str, start_port: int, max_attempts: int = 20) ->

for port in range(start_port, start_port + max_attempts):
with socket.socket(family, socket.SOCK_STREAM) as s:
s.settimeout(0.3) # Prevent WSL firewall hangs (dropped SYN packets)
try:
result = s.connect_ex((host, port))
except (socket.timeout, OSError):
# Port is likely available but firewall drops the probe
return port
if result != 0:
if s.connect_ex((host, port)) != 0:
return port
raise RuntimeError(f"No available port found in range {start_port}-{start_port + max_attempts - 1}")

Expand Down
32 changes: 0 additions & 32 deletions tests/regression/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,38 +93,6 @@ def test_regression_10_8_4_relative_url_not_backwards():
assert rel == "getting-started/"


# ---------------------------------------------------------------------------
# 10.9.5 — WSL port probe must not hang
# ---------------------------------------------------------------------------


def test_regression_10_9_5_port_probe_has_short_timeout(monkeypatch):
"""The port-finder must use a short socket timeout so a dropped SYN (WSL
firewall) doesn't hang the server startup for the default TCP timeout."""
import inspect

from docsforge import serve

src = inspect.getsource(serve._find_available_port)
assert "settimeout" in src
# Confirm the timeout is actually small (<= 1s) by exercising it.
timeouts = []

class FakeSocket:
def __enter__(self): return self
def __exit__(self, *a): pass
def settimeout(self, t): timeouts.append(t)
def connect_ex(self, addr): return 0 # port "in use"

monkeypatch.setattr(socket, "socket", lambda *a, **k: FakeSocket())
try:
serve._find_available_port("127.0.0.1", 8000, max_attempts=1)
except RuntimeError:
pass # all "in use" -> no port found, that's fine
assert timeouts, "settimeout was never called"
assert timeouts[0] <= 1.0


# ---------------------------------------------------------------------------
# 11.0.0b1 — privacy path normalization /. matched .icons -> _icons
# ---------------------------------------------------------------------------
Expand Down
14 changes: 0 additions & 14 deletions tests/unit/test_serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,6 @@ def connect_ex(self, addr): return 0 # always in use
with pytest.raises(RuntimeError):
_find_available_port("127.0.0.1", 8000, max_attempts=3)

def test_firewall_dropped_syn_returns_port(self, monkeypatch):
# A dropped SYN (firewall) raises socket.timeout/OSError -> port is free
class FakeSocket:
def __enter__(self): return self
def __exit__(self, *a): pass
def settimeout(self, t):
self.t = t
assert t <= 1.0, "probe must use a short timeout (WSL fix)"
def connect_ex(self, addr):
raise socket.timeout("dropped")

monkeypatch.setattr(socket, "socket", lambda *a, **k: FakeSocket())
assert _find_available_port("127.0.0.1", 8000) == 8000


# ---------------------------------------------------------------------------
# URL / path helpers
Expand Down