Skip to content

Commit abe8c2b

Browse files
authored
Merge pull request moby#5182 from tonistiigi/internal-syscall-err
errdefs: detect certain sycall errors as internal
2 parents c67b35e + d9a9a4d commit abe8c2b

File tree

5 files changed

+95
-31
lines changed

5 files changed

+95
-31
lines changed

errdefs/errdefs.go

Lines changed: 0 additions & 31 deletions
This file was deleted.

errdefs/internal.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package errdefs
2+
3+
import (
4+
"errors"
5+
"syscall"
6+
)
7+
8+
type internalErr struct {
9+
error
10+
}
11+
12+
func (internalErr) System() {}
13+
14+
func (err internalErr) Unwrap() error {
15+
return err.error
16+
}
17+
18+
type system interface {
19+
System()
20+
}
21+
22+
var _ system = internalErr{}
23+
24+
func Internal(err error) error {
25+
if err == nil {
26+
return nil
27+
}
28+
return internalErr{err}
29+
}
30+
31+
func IsInternal(err error) bool {
32+
var s system
33+
if errors.As(err, &s) {
34+
return true
35+
}
36+
37+
var errno syscall.Errno
38+
if errors.As(err, &errno) {
39+
if _, ok := isInternalSyscall(errno); ok {
40+
return true
41+
}
42+
}
43+
return false
44+
}
45+
46+
func IsResourceExhausted(err error) bool {
47+
var errno syscall.Errno
48+
if errors.As(err, &errno) {
49+
if v, ok := isInternalSyscall(errno); ok && v {
50+
return v
51+
}
52+
}
53+
return false
54+
}
55+
56+
func isInternalSyscall(err syscall.Errno) (bool, bool) {
57+
v, ok := syscallErrors()[err]
58+
return v, ok
59+
}

errdefs/internal_linux.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//go:build linux
2+
// +build linux
3+
4+
package errdefs
5+
6+
import (
7+
"syscall"
8+
9+
"golang.org/x/sys/unix"
10+
)
11+
12+
// syscallErrors returns a map of syscall errors that are considered internal.
13+
// value is true if the error is of type resource exhaustion, false otherwise.
14+
func syscallErrors() map[syscall.Errno]bool {
15+
return map[syscall.Errno]bool{
16+
unix.EIO: false, // I/O error
17+
unix.ENOMEM: true, // Out of memory
18+
unix.EFAULT: false, // Bad address
19+
unix.ENOSPC: true, // No space left on device
20+
unix.ENOTRECOVERABLE: false, // State not recoverable
21+
unix.EHWPOISON: false, // Memory page has hardware error
22+
}
23+
}

errdefs/internal_nolinux.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//go:build !linux
2+
// +build !linux
3+
4+
package errdefs
5+
6+
import "syscall"
7+
8+
func syscallErrors() map[syscall.Errno]bool {
9+
return nil
10+
}

util/grpcerrors/grpcerrors.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ func withDetails(ctx context.Context, s *status.Status, details ...proto.Message
9696

9797
func Code(err error) codes.Code {
9898
if errdefs.IsInternal(err) {
99+
if errdefs.IsResourceExhausted(err) {
100+
return codes.ResourceExhausted
101+
}
99102
return codes.Internal
100103
}
101104

0 commit comments

Comments
 (0)