internal/jsonrpc2: try to suppress unnecessary errors on shutdown

Even on successful shutdown, test logs contain a lot of "failed reading
header line: EOF". This can be distracting, or worse, misleading. Do our
best to suppress these error logs.

Updates golang/go#39130

Change-Id: I6ebe61100501f69c7490b418f53871b4e9704a00
Reviewed-on: https://go-review.googlesource.com/c/tools/+/237582
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/jsonrpc2/serve.go b/internal/jsonrpc2/serve.go
index 6d0a9dc..6589ed3 100644
--- a/internal/jsonrpc2/serve.go
+++ b/internal/jsonrpc2/serve.go
@@ -6,7 +6,9 @@
 
 import (
 	"context"
+	"errors"
 	"fmt"
+	"io"
 	"net"
 	"os"
 	"time"
@@ -105,7 +107,9 @@
 		case err := <-doneListening:
 			return err
 		case err := <-closedConns:
-			event.Error(ctx, "closed a connection", err)
+			if !isClosingError(err) {
+				event.Error(ctx, "closed a connection", err)
+			}
 			activeConns--
 			if activeConns == 0 {
 				connTimer.Reset(idleTimeout)
@@ -117,3 +121,19 @@
 		}
 	}
 }
+
+// isClosingError reports if the error occurs normally during the process of
+// closing a network connection. It uses imperfect heuristics that err on the
+// side of false negatives, and should not be used for anything critical.
+func isClosingError(err error) bool {
+	if errors.Is(err, io.EOF) {
+		return true
+	}
+	// Per https://github.com/golang/go/issues/4373, this error string should not
+	// change. This is not ideal, but since the worst that could happen here is
+	// some superfluous logging, it is acceptable.
+	if err.Error() == "use of closed network connection" {
+		return true
+	}
+	return false
+}