Symptom
On Korean Windows (and any non-English Windows), the endpoint latency probe reports ~687 ms for a target whose real RTT is ~32 ms. Values cluster around (2000 + 3×RTT)/3 with .33 fractions:
endpoint latency measured tunnel="..." target=8.8.8.8 via_tunnel=true reachable=true latency_ms=687.3333333333334
Measured RTT to the same target from a console at the same moment: 32 ms.
Root cause
internal/diag/ping.go shells out to ping and parses its output with English-only regexes (Average = (\d+)ms, time[=<]...ms). The helper launches ping with sysexec.Hide (CREATE_NO_WINDOW), and a console-less ping.exe emits output in the system MUI language — on this machine Korean, CP949-encoded:
8.8.8.8의 응답: 바이트=32 시간=33ms TTL=114
...
최소 = 32ms, 최대 = 33ms, 평균 = 32ms
(The same binary attached to an interactive console here produced English output, which is why the bug hides during manual testing.)
Both parsers miss, so the code falls through to the last-resort estimate elapsed_wall_clock / 3 (ping.go), and the wall clock for ping -n 3 includes the ~1 s inter-ping intervals: (≈2000 ms + 3×33 ms)/3 ≈ 687 ms. The .33 fractions are the ÷3.
Reproduced deterministically with a 15-line Go program calling diag.PingEndpoint("8.8.8.8") — returns 686.00 ms while the raw (Korean) ping output shows 32 ms.
Not the same bug as #15 (wrong probe target, fixed in 0.4.0): here the target is right and the parsing is wrong. Affects the tray/detail-pane latency display and anything else consuming latencyByTunnel on every non-English Windows install; non-English Linux/macOS locales are exposed through the same regexes if ping is localized.
Fix sketch
- Locale-agnostic reply parsing: extract
[=<]\s*([\d.]+)\s*ms from lines containing TTL= (locale-invariant token in IPv4 replies), falling back to all ...ms matches — 시간=33ms, Zeit=33ms, temps=33 ms, time<1ms all match.
- Unix branch: force
LC_ALL=C on the subprocess env so the existing parsers see canonical output.
- Keep the wall-clock estimate only as a truly-last resort; consider subtracting the inter-ping interval or dropping it, since a plausible-looking wrong number is worse than no number.
Symptom
On Korean Windows (and any non-English Windows), the endpoint latency probe reports ~687 ms for a target whose real RTT is ~32 ms. Values cluster around
(2000 + 3×RTT)/3with.33fractions:Measured RTT to the same target from a console at the same moment: 32 ms.
Root cause
internal/diag/ping.goshells out topingand parses its output with English-only regexes (Average = (\d+)ms,time[=<]...ms). The helper launches ping withsysexec.Hide(CREATE_NO_WINDOW), and a console-less ping.exe emits output in the system MUI language — on this machine Korean, CP949-encoded:(The same binary attached to an interactive console here produced English output, which is why the bug hides during manual testing.)
Both parsers miss, so the code falls through to the last-resort estimate
elapsed_wall_clock / 3(ping.go), and the wall clock forping -n 3includes the ~1 s inter-ping intervals: (≈2000 ms + 3×33 ms)/3 ≈ 687 ms. The.33fractions are the ÷3.Reproduced deterministically with a 15-line Go program calling
diag.PingEndpoint("8.8.8.8")— returns 686.00 ms while the raw (Korean) ping output shows 32 ms.Not the same bug as #15 (wrong probe target, fixed in 0.4.0): here the target is right and the parsing is wrong. Affects the tray/detail-pane latency display and anything else consuming
latencyByTunnelon every non-English Windows install; non-English Linux/macOS locales are exposed through the same regexes ifpingis localized.Fix sketch
[=<]\s*([\d.]+)\s*msfrom lines containingTTL=(locale-invariant token in IPv4 replies), falling back to all...msmatches —시간=33ms,Zeit=33ms,temps=33 ms,time<1msall match.LC_ALL=Con the subprocess env so the existing parsers see canonical output.