Skip to content

Commit 9c18842

Browse files
committed
go-selinux: retry on EINTR
Wrap some syscalls (lgetattr, lsetattr, fstatfs, statfs) to retry on EINTR. Related: - containers/storage#757 - https://go-review.googlesource.com/c/go/+/249178 - golang/go#38033 Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent bca2471 commit 9c18842

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

go-selinux/selinux_linux.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func verifySELinuxfsMount(mnt string) bool {
111111
if err == nil {
112112
break
113113
}
114-
if err == unix.EAGAIN {
114+
if err == unix.EAGAIN || err == unix.EINTR {
115115
continue
116116
}
117117
return false
@@ -250,8 +250,17 @@ func getSELinuxPolicyRoot() string {
250250
}
251251

252252
func isProcHandle(fh *os.File) error {
253-
var buf unix.Statfs_t
254-
err := unix.Fstatfs(int(fh.Fd()), &buf)
253+
var (
254+
buf unix.Statfs_t
255+
err error
256+
)
257+
258+
for {
259+
err = unix.Fstatfs(int(fh.Fd()), &buf)
260+
if err != unix.EINTR {
261+
break
262+
}
263+
}
255264
if err != nil {
256265
return errors.Wrapf(err, "statfs(%q) failed", fh.Name())
257266
}
@@ -307,9 +316,17 @@ func setFileLabel(fpath string, label string) error {
307316
if fpath == "" {
308317
return ErrEmptyPath
309318
}
310-
if err := unix.Lsetxattr(fpath, xattrNameSelinux, []byte(label), 0); err != nil {
319+
var err error
320+
for {
321+
err = unix.Lsetxattr(fpath, xattrNameSelinux, []byte(label), 0)
322+
if err != unix.EINTR {
323+
break
324+
}
325+
}
326+
if err != nil {
311327
return errors.Wrapf(err, "failed to set file label on %s", fpath)
312328
}
329+
313330
return nil
314331
}
315332

go-selinux/xattrs.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,35 @@ import (
66
"golang.org/x/sys/unix"
77
)
88

9-
// Returns a []byte slice if the xattr is set and nil otherwise
10-
// Requires path and its attribute as arguments
11-
func lgetxattr(path string, attr string) ([]byte, error) {
9+
// lgetxattr returns a []byte slice containing the value of
10+
// an extended attribute attr set for path.
11+
func lgetxattr(path, attr string) ([]byte, error) {
1212
// Start with a 128 length byte array
1313
dest := make([]byte, 128)
14-
sz, errno := unix.Lgetxattr(path, attr, dest)
14+
sz, errno := doLgetxattr(path, attr, dest)
1515
for errno == unix.ERANGE {
1616
// Buffer too small, use zero-sized buffer to get the actual size
17-
sz, errno = unix.Lgetxattr(path, attr, []byte{})
17+
sz, errno = doLgetxattr(path, attr, []byte{})
1818
if errno != nil {
1919
return nil, errno
2020
}
2121

2222
dest = make([]byte, sz)
23-
sz, errno = unix.Lgetxattr(path, attr, dest)
23+
sz, errno = doLgetxattr(path, attr, dest)
2424
}
2525
if errno != nil {
2626
return nil, errno
2727
}
2828

2929
return dest[:sz], nil
3030
}
31+
32+
// doLgetxattr is a wrapper that retries on EINTR
33+
func doLgetxattr(path, attr string, dest []byte) (int, error) {
34+
for {
35+
sz, err := unix.Lgetxattr(path, attr, dest)
36+
if err != unix.EINTR {
37+
return sz, err
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)