Skip to content

Commit ea8b0ac

Browse files
committed
all: remove os.ErrTemporary
As discussed in #32463 (comment) the classification of deadline-based timeouts as "temporary" errors is a historical accident. I/O timeouts used to be duration-based, so they really were temporary--retrying a timed-out operation could succeed. Now that they're deadline-based, timeouts aren't temporary unless you reset the deadline. Drop ErrTemporary from Go 1.13, since its definition is wrong. We'll consider putting it back in Go 1.14 with a clear definition and deprecate net.OpError.Temporary. Fixes #32463 Change-Id: I70cda664590d8872541e17409a5780da76920891 Reviewed-on: https://go-review.googlesource.com/c/go/+/188398 Reviewed-by: Jonathan Amsterdam <[email protected]>
1 parent 8a317eb commit ea8b0ac

16 files changed

+17
-70
lines changed

api/go1.13.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ pkg os (netbsd-arm64), const O_SYNC = 128
237237
pkg os (netbsd-arm64), const O_TRUNC = 1024
238238
pkg os (netbsd-arm64), const PathListSeparator = 58
239239
pkg os (netbsd-arm64), const PathSeparator = 47
240-
pkg os, var ErrTemporary error
241240
pkg os, var ErrTimeout error
242241
pkg path/filepath (netbsd-arm64-cgo), const ListSeparator = 58
243242
pkg path/filepath (netbsd-arm64-cgo), const Separator = 47

src/context/context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func (deadlineExceededError) Error() string { return "context deadline exceede
164164
func (deadlineExceededError) Timeout() bool { return true }
165165
func (deadlineExceededError) Temporary() bool { return true }
166166
func (deadlineExceededError) Is(target error) bool {
167-
return target == oserror.ErrTimeout || target == oserror.ErrTemporary
167+
return target == oserror.ErrTimeout
168168
}
169169

170170
// An emptyCtx is never canceled, has no values, and has no deadline. It is not

src/internal/oserror/errors.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ var (
1515
ErrExist = errors.New("file already exists")
1616
ErrNotExist = errors.New("file does not exist")
1717
ErrClosed = errors.New("file already closed")
18-
ErrTemporary = temporaryError{}
1918
ErrTimeout = timeoutError{}
2019
)
2120

@@ -45,20 +44,3 @@ func IsTimeout(err error) bool {
4544
}
4645
return false
4746
}
48-
49-
// IsTemporary reports whether err indicates a temporary condition.
50-
func IsTemporary(err error) bool {
51-
for err != nil {
52-
if err == ErrTemporary {
53-
return true
54-
}
55-
if x, ok := err.(interface{ Temporary() bool }); ok {
56-
return x.Temporary()
57-
}
58-
if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(ErrTemporary) {
59-
return true
60-
}
61-
err = errors.Unwrap(err)
62-
}
63-
return false
64-
}

src/internal/oserror/errors_test.go

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ import (
99
)
1010

1111
type ttError struct {
12-
timeout bool
13-
temporary bool
12+
timeout bool
1413
}
1514

1615
func (e ttError) Error() string {
17-
return fmt.Sprintf("ttError{timeout:%v temporary:%v}", e.timeout, e.temporary)
16+
return fmt.Sprintf("ttError{timeout:%v}", e.timeout)
1817
}
19-
func (e ttError) Timeout() bool { return e.timeout }
20-
func (e ttError) Temporary() bool { return e.temporary }
18+
func (e ttError) Timeout() bool { return e.timeout }
2119

2220
type isError struct {
2321
err error
@@ -43,21 +41,3 @@ func TestIsTimeout(t *testing.T) {
4341
}
4442
}
4543
}
46-
47-
func TestIsTemporary(t *testing.T) {
48-
for _, test := range []struct {
49-
want bool
50-
err error
51-
}{
52-
{true, ttError{temporary: true}},
53-
{true, isError{os.ErrTemporary}},
54-
{true, os.ErrTemporary},
55-
{true, fmt.Errorf("wrap: %w", os.ErrTemporary)},
56-
{false, ttError{temporary: false}},
57-
{false, errors.New("error")},
58-
} {
59-
if got, want := oserror.IsTemporary(test.err), test.want; got != want {
60-
t.Errorf("IsTemporary(err) = %v, want %v\n%+v", got, want, test.err)
61-
}
62-
}
63-
}

src/internal/poll/fd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (e *TimeoutError) Timeout() bool { return true }
4848
func (e *TimeoutError) Temporary() bool { return true }
4949

5050
func (e *TimeoutError) Is(target error) bool {
51-
return target == oserror.ErrTimeout || target == oserror.ErrTemporary
51+
return target == oserror.ErrTimeout
5252
}
5353

5454
// ErrNotPollable is returned when the file or socket is not suitable

src/net/cgo_unix.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ func (eai addrinfoErrno) Timeout() bool { return false }
4040

4141
func (eai addrinfoErrno) Is(target error) bool {
4242
switch target {
43-
case os.ErrTemporary:
44-
return eai.Temporary()
4543
case os.ErrTimeout:
4644
return eai.Timeout()
4745
}

src/net/http/transport.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,8 +2288,6 @@ func (e *httpError) Is(target error) bool {
22882288
switch target {
22892289
case os.ErrTimeout:
22902290
return e.timeout
2291-
case os.ErrTemporary:
2292-
return true
22932291
}
22942292
return false
22952293
}
@@ -2629,7 +2627,7 @@ func (tlsHandshakeTimeoutError) Temporary() bool { return true }
26292627
func (tlsHandshakeTimeoutError) Error() string { return "net/http: TLS handshake timeout" }
26302628

26312629
func (tlsHandshakeTimeoutError) Is(target error) bool {
2632-
return target == os.ErrTimeout || target == os.ErrTemporary
2630+
return target == os.ErrTimeout
26332631
}
26342632

26352633
// fakeLocker is a sync.Locker which does nothing. It's used to guard

src/net/net.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -518,8 +518,6 @@ func (e *OpError) Temporary() bool {
518518

519519
func (e *OpError) Is(target error) bool {
520520
switch target {
521-
case os.ErrTemporary:
522-
return e.Temporary()
523521
case os.ErrTimeout:
524522
return e.Timeout()
525523
}
@@ -619,8 +617,6 @@ func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
619617

620618
func (e *DNSError) Is(target error) bool {
621619
switch target {
622-
case os.ErrTemporary:
623-
return e.Temporary()
624620
case os.ErrTimeout:
625621
return e.Timeout()
626622
}

src/net/pipe.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (timeoutError) Timeout() bool { return true }
8686
func (timeoutError) Temporary() bool { return true }
8787

8888
func (timeoutError) Is(target error) bool {
89-
return target == os.ErrTemporary || target == os.ErrTimeout
89+
return target == os.ErrTimeout
9090
}
9191

9292
type pipeAddr struct{}

src/net/url/url.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,16 @@ type Error struct {
2626
Err error
2727
}
2828

29-
func (e *Error) Unwrap() error { return e.Err }
30-
func (e *Error) Error() string { return e.Op + " " + e.URL + ": " + e.Err.Error() }
31-
func (e *Error) Timeout() bool { return oserror.IsTimeout(e.Err) }
32-
func (e *Error) Temporary() bool { return oserror.IsTemporary(e.Err) }
29+
func (e *Error) Unwrap() error { return e.Err }
30+
func (e *Error) Error() string { return e.Op + " " + e.URL + ": " + e.Err.Error() }
31+
func (e *Error) Timeout() bool { return oserror.IsTimeout(e.Err) }
32+
33+
func (e *Error) Temporary() bool {
34+
t, ok := e.Err.(interface {
35+
Temporary() bool
36+
})
37+
return ok && t.Temporary()
38+
}
3339

3440
func ishex(c byte) bool {
3541
switch {

src/os/error.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ var (
2323
ErrNotExist = errNotExist() // "file does not exist"
2424
ErrClosed = errClosed() // "file already closed"
2525
ErrTimeout = errTimeout() // "deadline exceeded"
26-
ErrTemporary = errTemporary() // "temporary error"
2726
ErrNoDeadline = errNoDeadline() // "file type does not support deadline"
2827
)
2928

@@ -33,7 +32,6 @@ func errExist() error { return oserror.ErrExist }
3332
func errNotExist() error { return oserror.ErrNotExist }
3433
func errClosed() error { return oserror.ErrClosed }
3534
func errTimeout() error { return oserror.ErrTimeout }
36-
func errTemporary() error { return oserror.ErrTemporary }
3735
func errNoDeadline() error { return poll.ErrNoDeadline }
3836

3937
type timeout interface {

src/syscall/syscall_js.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ func (e Errno) Error() string {
5858

5959
func (e Errno) Is(target error) bool {
6060
switch target {
61-
case oserror.ErrTemporary:
62-
return e.Temporary()
6361
case oserror.ErrTimeout:
6462
return e.Timeout()
6563
case oserror.ErrPermission:

src/syscall/syscall_nacl.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ func (e Errno) Error() string {
6565

6666
func (e Errno) Is(target error) bool {
6767
switch target {
68-
case oserror.ErrTemporary:
69-
return e.Temporary()
7068
case oserror.ErrTimeout:
7169
return e.Timeout()
7270
case oserror.ErrPermission:

src/syscall/syscall_plan9.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ func NewError(s string) error { return ErrorString(s) }
2929

3030
func (e ErrorString) Is(target error) bool {
3131
switch target {
32-
case oserror.ErrTemporary:
33-
return e.Temporary()
3432
case oserror.ErrTimeout:
3533
return e.Timeout()
3634
case oserror.ErrPermission:

src/syscall/syscall_unix.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,6 @@ func (e Errno) Error() string {
121121

122122
func (e Errno) Is(target error) bool {
123123
switch target {
124-
case oserror.ErrTemporary:
125-
return e.Temporary()
126124
case oserror.ErrTimeout:
127125
return e.Timeout()
128126
case oserror.ErrPermission:

src/syscall/syscall_windows.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ const _ERROR_BAD_NETPATH = Errno(53)
115115

116116
func (e Errno) Is(target error) bool {
117117
switch target {
118-
case oserror.ErrTemporary:
119-
return e.Temporary()
120118
case oserror.ErrTimeout:
121119
return e.Timeout()
122120
case oserror.ErrPermission:

0 commit comments

Comments
 (0)