From e985245cd520cabe4bd3d99058d1089aac50cf45 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 2 Apr 2021 14:36:36 -0700 Subject: [PATCH] net: make ErrClosed and ParseError implement net.Error Fixes #45357 Change-Id: Iafd41fff232a89be4c88d4b1d66bc3c04d888bcc Reviewed-on: https://go-review.googlesource.com/c/go/+/307030 Trust: Ian Lance Taylor Trust: Josh Bleecher Snyder Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Josh Bleecher Snyder --- src/internal/poll/fd.go | 19 +++++++++++++++---- src/net/net.go | 5 ++++- src/net/net_test.go | 20 ++++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/internal/poll/fd.go b/src/internal/poll/fd.go index b72ea3d55c245..69a90054d3575 100644 --- a/src/internal/poll/fd.go +++ b/src/internal/poll/fd.go @@ -13,11 +13,22 @@ import ( "errors" ) -// ErrNetClosing is returned when a network descriptor is used after -// it has been closed. Keep this string consistent because of issue -// #4373: since historically programs have not been able to detect +// errNetClosing is the type of the variable ErrNetClosing. +// This is used to implement the net.Error interface. +type errNetClosing struct{} + +// Error returns the error message for ErrNetClosing. +// Keep this string consistent because of issue #4373: +// since historically programs have not been able to detect // this error, they look for the string. -var ErrNetClosing = errors.New("use of closed network connection") +func (e errNetClosing) Error() string { return "use of closed network connection" } + +func (e errNetClosing) Timeout() bool { return false } +func (e errNetClosing) Temporary() bool { return false } + +// ErrNetClosing is returned when a network descriptor is used after +// it has been closed. +var ErrNetClosing = errNetClosing{} // ErrFileClosing is returned when a file descriptor is used after it // has been closed. diff --git a/src/net/net.go b/src/net/net.go index 7e172b708e054..a7c65fff79526 100644 --- a/src/net/net.go +++ b/src/net/net.go @@ -539,6 +539,9 @@ type ParseError struct { func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text } +func (e *ParseError) Timeout() bool { return false } +func (e *ParseError) Temporary() bool { return false } + type AddrError struct { Err string Addr string @@ -642,7 +645,7 @@ var errClosed = poll.ErrNetClosing // another goroutine before the I/O is completed. This may be wrapped // in another error, and should normally be tested using // errors.Is(err, net.ErrClosed). -var ErrClosed = errClosed +var ErrClosed error = errClosed type writerOnly struct { io.Writer diff --git a/src/net/net_test.go b/src/net/net_test.go index 6d6299e74ad6e..6e7be4db23c1e 100644 --- a/src/net/net_test.go +++ b/src/net/net_test.go @@ -588,3 +588,23 @@ func TestNotTemporaryRead(t *testing.T) { } withTCPConnPair(t, client, server) } + +// The various errors should implement the Error interface. +func TestErrors(t *testing.T) { + var ( + _ Error = &OpError{} + _ Error = &ParseError{} + _ Error = &AddrError{} + _ Error = UnknownNetworkError("") + _ Error = InvalidAddrError("") + _ Error = &timeoutError{} + _ Error = &DNSConfigError{} + _ Error = &DNSError{} + ) + + // ErrClosed was introduced as type error, so we can't check + // it using a declaration. + if _, ok := ErrClosed.(Error); !ok { + t.Fatal("ErrClosed does not implement Error") + } +}