ping: Don't log idle timeout as error - #18
Open
gonghao wants to merge 1 commit into
Open
Conversation
`loopRead` sets a read deadline of `d.timeout` on every iteration, so a
destination that stops receiving echo replies ends its loop with
`os.ErrDeadlineExceeded` (gonet returns its own `net.Error` with
`Timeout() == true`). That is the intended lifetime end of an idle ICMP
session — `defer d.Close()` right above it exists for exactly this path.
`E.IsClosed` only covers EOF/ErrClosed/EPIPE/ECONNRESET/ENOTCONN, so the
deadline error falls through to `ErrorContext` and every normally
finished ICMP session leaves behind
receive ICMP echo reply: read ip 192.168.1.1: i/o timeout
The check dates back to the initial commit, when `ReadIP` blocked
forever and the only possible errors were real ones. `SetReadDeadline`
was introduced later without updating it.
Use `E.IsClosedOrCanceled`, which additionally covers `E.IsTimeout` via
the `net.Error` interface and therefore handles both the syscall and the
gVisor conn.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every ICMP session that finishes normally leaves an
ERRORline behind:The two lines are exactly
idleTimeoutapart (measured:16:58:11.780184→16:58:21.780487, i.e. 10.0003s), and the pings themselves succeed — the client sees 0% loss. On a router where a device does periodic connectivity probes, this accumulates hundreds ofERRORentries that are pure noise.The address in the message is also misleading: it is the local address the raw socket got bound to (
ip route get 8.8.8.8→src 192.168.10.1), not the ping target, so every direct ICMP session reports the same IP.Cause
loopReadre-arms a read deadline on every iteration, so a destination that stops receiving echo replies exits with a deadline error. That is the intended end of an idle session — thedefer d.Close()added in the same commit exists for exactly this path.But the error classification was never updated to match.
E.IsClosedonly coversio.EOF,net.ErrClosed,io.ErrClosedPipe,os.ErrClosed,EPIPE,ECONNRESETandENOTCONN, so the deadline error falls through toErrorContext.The check dates back to 53dbe7b ("Add ping support"), where
ReadIPblocked forever and the only possible errors were genuine failures — correct at the time. 5133fee ("ping: Add timeout to destinations") introducedSetReadDeadlineand a third, benign exit path, but left the branch untouched.Fix
Use
E.IsClosedOrCanceled, which isIsClosed || IsCanceled || IsTimeout.E.IsTimeoutmatches through thenet.Errorinterface, so it covers both conns:ping/destination.go— syscall conn, returnsos.ErrDeadlineExceededping/destination_gvisor.go—gonetreturns its owntimeoutError{}withTimeout() == true; note thaterrors.Is(err, os.ErrDeadlineExceeded)would not work here even though the message string is identicalGenuine timeouts are not lost: in both loops the re-armed deadline is the only source of a timeout error.
Verification
go buildandgo vetpass forlinux,darwin,windowsandandroid/arm64, with and without thewith_gvisortag.go test ./ping/...passes.