fd_posix.mx raw
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 //go:build unix || (js && wasm) || wasip1 || windows
6
7 package poll
8
9 import (
10 "io"
11 "syscall"
12 )
13
14 // eofError returns io.EOF when fd is available for reading end of
15 // file.
16 func (fd *FD) eofError(n int, err error) error {
17 if n == 0 && err == nil && fd.ZeroReadIsEOF {
18 return io.EOF
19 }
20 return err
21 }
22
23 // Shutdown wraps syscall.Shutdown.
24 func (fd *FD) Shutdown(how int) error {
25 if err := fd.incref(); err != nil {
26 return err
27 }
28 defer fd.decref()
29 return syscall.Shutdown(fd.Sysfd, how)
30 }
31
32 // Fchown wraps syscall.Fchown.
33 func (fd *FD) Fchown(uid, gid int) error {
34 if err := fd.incref(); err != nil {
35 return err
36 }
37 defer fd.decref()
38 return ignoringEINTR(func() error {
39 return syscall.Fchown(fd.Sysfd, uid, gid)
40 })
41 }
42
43 // Ftruncate wraps syscall.Ftruncate.
44 func (fd *FD) Ftruncate(size int64) error {
45 if err := fd.incref(); err != nil {
46 return err
47 }
48 defer fd.decref()
49 return ignoringEINTR(func() error {
50 return syscall.Ftruncate(fd.Sysfd, size)
51 })
52 }
53
54 // RawControl invokes the user-defined function f for a non-IO
55 // operation.
56 func (fd *FD) RawControl(f func(uintptr)) error {
57 if err := fd.incref(); err != nil {
58 return err
59 }
60 defer fd.decref()
61 f(uintptr(fd.Sysfd))
62 return nil
63 }
64
65 // ignoringEINTR makes a function call and repeats it if it returns
66 // an EINTR error. This appears to be required even though we install all
67 // signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.
68 // Also #20400 and #36644 are issues in which a signal handler is
69 // installed without setting SA_RESTART. None of these are the common case,
70 // but there are enough of them that it seems that we can't avoid
71 // an EINTR loop.
72 func ignoringEINTR(fn func() error) error {
73 for {
74 err := fn()
75 if err != syscall.EINTR {
76 return err
77 }
78 }
79 }
80
81 // ignoringEINTR2 is ignoringEINTR, but returning an additional value.
82 func ignoringEINTR2[T any](fn func() (T, error)) (T, error) {
83 for {
84 v, err := fn()
85 if err != syscall.EINTR {
86 return v, err
87 }
88 }
89 }
90