if testing.Short() {
n = 1000
}
+ switch runtime.GOOS {
+ case "darwin", "freebsd", "openbsd", "windows":
+ // Non-Linux systems take a long time to figure
+ // out that there is nothing listening on localhost.
+ n = 100
+ }
for i := 0; i < n; i++ {
c, err := Dial("tcp", addr)
if err == nil {
package net
import (
+ "errors"
"io"
"os"
"sync"
// locking/lifetime of sysfd
sysmu sync.Mutex
sysref int
+
+ // must lock both sysmu and pollserver to write
+ // can lock either to read
closing bool
// immutable until Close
sotype int
isConnected bool
sysfile *os.File
- cr chan bool
- cw chan bool
+ cr chan error
+ cw chan error
net string
laddr Addr
raddr Addr
deadline int64 // next deadline (nsec since 1970)
}
-func (s *pollServer) AddFD(fd *netFD, mode int) {
+func (s *pollServer) AddFD(fd *netFD, mode int) error {
+ s.Lock()
intfd := fd.sysfd
- if intfd < 0 {
+ if intfd < 0 || fd.closing {
// fd closed underfoot
- if mode == 'r' {
- fd.cr <- true
- } else {
- fd.cw <- true
- }
- return
+ s.Unlock()
+ return errClosing
}
- s.Lock()
-
var t int64
key := intfd << 1
if mode == 'r' {
if wake {
doWakeup = true
}
-
s.Unlock()
if doWakeup {
s.Wakeup()
}
+ return nil
+}
+
+// Evict evicts fd from the pending list, unblocking
+// any I/O running on fd. The caller must have locked
+// pollserver.
+func (s *pollServer) Evict(fd *netFD) {
+ if s.pending[fd.sysfd<<1] == fd {
+ s.WakeFD(fd, 'r', errClosing)
+ s.poll.DelFD(fd.sysfd, 'r')
+ delete(s.pending, fd.sysfd<<1)
+ }
+ if s.pending[fd.sysfd<<1|1] == fd {
+ s.WakeFD(fd, 'w', errClosing)
+ s.poll.DelFD(fd.sysfd, 'w')
+ delete(s.pending, fd.sysfd<<1|1)
+ }
}
var wakeupbuf [1]byte
return netfd
}
-func (s *pollServer) WakeFD(fd *netFD, mode int) {
+func (s *pollServer) WakeFD(fd *netFD, mode int, err error) {
if mode == 'r' {
for fd.ncr > 0 {
fd.ncr--
- fd.cr <- true
+ fd.cr <- err
}
} else {
for fd.ncw > 0 {
fd.ncw--
- fd.cw <- true
+ fd.cw <- err
}
}
}
s.poll.DelFD(fd.sysfd, mode)
fd.wdeadline = -1
}
- s.WakeFD(fd, mode)
+ s.WakeFD(fd, mode, nil)
} else if next_deadline == 0 || t < next_deadline {
next_deadline = t
}
print("pollServer: unexpected wakeup for fd=", fd, " mode=", string(mode), "\n")
continue
}
- s.WakeFD(netfd, mode)
+ s.WakeFD(netfd, mode, nil)
}
}
}
-func (s *pollServer) WaitRead(fd *netFD) {
- s.AddFD(fd, 'r')
- <-fd.cr
+func (s *pollServer) WaitRead(fd *netFD) error {
+ err := s.AddFD(fd, 'r')
+ if err == nil {
+ err = <-fd.cr
+ }
+ return err
}
-func (s *pollServer) WaitWrite(fd *netFD) {
- s.AddFD(fd, 'w')
- <-fd.cw
+func (s *pollServer) WaitWrite(fd *netFD) error {
+ err := s.AddFD(fd, 'w')
+ if err == nil {
+ err = <-fd.cw
+ }
+ return err
}
// Network FD methods.
sotype: sotype,
net: net,
}
- netfd.cr = make(chan bool, 1)
- netfd.cw = make(chan bool, 1)
+ netfd.cr = make(chan error, 1)
+ netfd.cw = make(chan error, 1)
return netfd, nil
}
func (fd *netFD) connect(ra syscall.Sockaddr) error {
err := syscall.Connect(fd.sysfd, ra)
if err == syscall.EINPROGRESS {
- pollserver.WaitWrite(fd)
+ if err = pollserver.WaitWrite(fd); err != nil {
+ return err
+ }
var e int
e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
if err != nil {
return err
}
+var errClosing = errors.New("use of closed network connection")
+
// Add a reference to this fd.
-func (fd *netFD) incref() {
+// If closing==true, pollserver must be locked; mark the fd as closing.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) incref(closing bool) error {
+ if fd == nil {
+ return errClosing
+ }
fd.sysmu.Lock()
+ if fd.closing {
+ fd.sysmu.Unlock()
+ return errClosing
+ }
fd.sysref++
+ if closing {
+ fd.closing = true
+ }
fd.sysmu.Unlock()
+ return nil
}
// Remove a reference to this FD and close if we've been asked to do so (and
// there are no references left.
func (fd *netFD) decref() {
+ if fd == nil {
+ return
+ }
fd.sysmu.Lock()
fd.sysref--
- if fd.closing && fd.sysref == 0 && fd.sysfd >= 0 {
- // In case the user has set linger, switch to blocking mode so
- // the close blocks. As long as this doesn't happen often, we
- // can handle the extra OS processes. Otherwise we'll need to
- // use the pollserver for Close too. Sigh.
- syscall.SetNonblock(fd.sysfd, false)
+ if fd.closing && fd.sysref == 0 && fd.sysfile != nil {
fd.sysfile.Close()
fd.sysfile = nil
fd.sysfd = -1
}
func (fd *netFD) Close() error {
- if fd == nil || fd.sysfile == nil {
- return os.EINVAL
- }
-
- fd.incref()
- syscall.Shutdown(fd.sysfd, syscall.SHUT_RDWR)
- fd.closing = true
+ pollserver.Lock() // needed for both fd.incref(true) and pollserver.Evict
+ defer pollserver.Unlock()
+ if err := fd.incref(true); err != nil {
+ return err
+ }
+ // Unblock any I/O. Once it all unblocks and returns,
+ // so that it cannot be referring to fd.sysfd anymore,
+ // the final decref will close fd.sysfd. This should happen
+ // fairly quickly, since all the I/O is non-blocking, and any
+ // attempts to block in the pollserver will return errClosing.
+ pollserver.Evict(fd)
fd.decref()
return nil
}
func (fd *netFD) shutdown(how int) error {
- if fd == nil || fd.sysfile == nil {
- return os.EINVAL
+ if err := fd.incref(false); err != nil {
+ return err
}
+ defer fd.decref()
err := syscall.Shutdown(fd.sysfd, how)
if err != nil {
return &OpError{"shutdown", fd.net, fd.laddr, err}
}
func (fd *netFD) Read(p []byte) (n int, err error) {
- if fd == nil {
- return 0, os.EINVAL
- }
fd.rio.Lock()
defer fd.rio.Unlock()
- fd.incref()
- defer fd.decref()
- if fd.sysfile == nil {
- return 0, os.EINVAL
+ if err := fd.incref(false); err != nil {
+ return 0, err
}
+ defer fd.decref()
for {
- n, err = syscall.Read(int(fd.sysfile.Fd()), p)
+ n, err = syscall.Read(int(fd.sysfd), p)
if err == syscall.EAGAIN {
+ err = errTimeout
if fd.rdeadline >= 0 {
- pollserver.WaitRead(fd)
- continue
+ if err = pollserver.WaitRead(fd); err == nil {
+ continue
+ }
}
- err = errTimeout
}
if err != nil {
n = 0
}
func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
- if fd == nil || fd.sysfile == nil {
- return 0, nil, os.EINVAL
- }
fd.rio.Lock()
defer fd.rio.Unlock()
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, nil, err
+ }
defer fd.decref()
for {
n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
if err == syscall.EAGAIN {
+ err = errTimeout
if fd.rdeadline >= 0 {
- pollserver.WaitRead(fd)
- continue
+ if err = pollserver.WaitRead(fd); err == nil {
+ continue
+ }
}
- err = errTimeout
}
if err != nil {
n = 0
}
break
}
- if err != nil {
+ if err != nil && err != io.EOF {
err = &OpError{"read", fd.net, fd.laddr, err}
}
return
}
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
- if fd == nil || fd.sysfile == nil {
- return 0, 0, 0, nil, os.EINVAL
- }
fd.rio.Lock()
defer fd.rio.Unlock()
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, 0, 0, nil, err
+ }
defer fd.decref()
for {
n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
if err == syscall.EAGAIN {
+ err = errTimeout
if fd.rdeadline >= 0 {
- pollserver.WaitRead(fd)
- continue
+ if err = pollserver.WaitRead(fd); err == nil {
+ continue
+ }
}
- err = errTimeout
}
if err == nil && n == 0 {
err = io.EOF
}
func (fd *netFD) Write(p []byte) (int, error) {
- if fd == nil {
- return 0, os.EINVAL
- }
fd.wio.Lock()
defer fd.wio.Unlock()
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
if fd.sysfile == nil {
return 0, os.EINVAL
nn := 0
for {
var n int
- n, err = syscall.Write(int(fd.sysfile.Fd()), p[nn:])
+ n, err = syscall.Write(int(fd.sysfd), p[nn:])
if n > 0 {
nn += n
}
break
}
if err == syscall.EAGAIN {
+ err = errTimeout
if fd.wdeadline >= 0 {
- pollserver.WaitWrite(fd)
- continue
+ if err = pollserver.WaitWrite(fd); err == nil {
+ continue
+ }
}
- err = errTimeout
}
if err != nil {
n = 0
}
func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
- if fd == nil || fd.sysfile == nil {
- return 0, os.EINVAL
- }
fd.wio.Lock()
defer fd.wio.Unlock()
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
for {
err = syscall.Sendto(fd.sysfd, p, 0, sa)
if err == syscall.EAGAIN {
+ err = errTimeout
if fd.wdeadline >= 0 {
- pollserver.WaitWrite(fd)
- continue
+ if err = pollserver.WaitWrite(fd); err == nil {
+ continue
+ }
}
- err = errTimeout
}
break
}
}
func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
- if fd == nil || fd.sysfile == nil {
- return 0, 0, os.EINVAL
- }
fd.wio.Lock()
defer fd.wio.Unlock()
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, 0, err
+ }
defer fd.decref()
for {
err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
if err == syscall.EAGAIN {
+ err = errTimeout
if fd.wdeadline >= 0 {
- pollserver.WaitWrite(fd)
- continue
+ if err = pollserver.WaitWrite(fd); err == nil {
+ continue
+ }
}
- err = errTimeout
}
break
}
}
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
- if fd == nil || fd.sysfile == nil {
- return nil, os.EINVAL
+ if err := fd.incref(false); err != nil {
+ return nil, err
}
-
- fd.incref()
defer fd.decref()
// See ../syscall/exec.go for description of ForkLock.
var s int
var rsa syscall.Sockaddr
for {
- if fd.closing {
- return nil, os.EINVAL
- }
syscall.ForkLock.RLock()
s, rsa, err = syscall.Accept(fd.sysfd)
if err != nil {
syscall.ForkLock.RUnlock()
if err == syscall.EAGAIN {
+ err = errTimeout
if fd.rdeadline >= 0 {
- pollserver.WaitRead(fd)
- continue
+ if err = pollserver.WaitRead(fd); err == nil {
+ continue
+ }
}
- err = errTimeout
}
return nil, &OpError{"accept", fd.net, fd.laddr, err}
}
return syscall.Connect(fd.sysfd, ra)
}
+var errClosing = errors.New("use of closed network connection")
+
// Add a reference to this fd.
-func (fd *netFD) incref() {
+// If closing==true, mark the fd as closing.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) incref(closing bool) error {
+ if fd == nil {
+ return errClosing
+ }
fd.sysmu.Lock()
+ if fd.closing {
+ fd.sysmu.Unlock()
+ return errClosing
+ }
fd.sysref++
+ if closing {
+ fd.closing = true
+ }
+ closing = fd.closing
fd.sysmu.Unlock()
+ return nil
}
// Remove a reference to this FD and close if we've been asked to do so (and
func (fd *netFD) decref() {
fd.sysmu.Lock()
fd.sysref--
- if fd.closing && fd.sysref == 0 && fd.sysfd != syscall.InvalidHandle {
+ // NOTE(rsc): On Unix we check fd.sysref == 0 here before closing,
+ // but on Windows we have no way to wake up the blocked I/O other
+ // than closing the socket (or calling Shutdown, which breaks other
+ // programs that might have a reference to the socket). So there is
+ // a small race here that we might close fd.sysfd and then some other
+ // goroutine might start a read of fd.sysfd (having read it before we
+ // write InvalidHandle to it), which might refer to some other file
+ // if the specific handle value gets reused. I think handle values on
+ // Windows are not reused as aggressively as file descriptors on Unix,
+ // so this might be tolerable.
+ if fd.closing && fd.sysfd != syscall.InvalidHandle {
// In case the user has set linger, switch to blocking mode so
// the close blocks. As long as this doesn't happen often, we
// can handle the extra OS processes. Otherwise we'll need to
}
func (fd *netFD) Close() error {
- if fd == nil || fd.sysfd == syscall.InvalidHandle {
- return os.EINVAL
+ if err := fd.incref(true); err != nil {
+ return err
}
-
- fd.incref()
- syscall.Shutdown(fd.sysfd, syscall.SHUT_RDWR)
- fd.closing = true
fd.decref()
return nil
}
}
fd.rio.Lock()
defer fd.rio.Unlock()
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
if fd.sysfd == syscall.InvalidHandle {
return 0, os.EINVAL
}
fd.rio.Lock()
defer fd.rio.Unlock()
- fd.incref()
- defer fd.decref()
- if fd.sysfd == syscall.InvalidHandle {
- return 0, nil, os.EINVAL
+ if err := fd.incref(false); err != nil {
+ return 0, nil, err
}
+ defer fd.decref()
var o readFromOp
o.Init(fd, buf, 'r')
o.rsan = int32(unsafe.Sizeof(o.rsa))
}
fd.wio.Lock()
defer fd.wio.Unlock()
- fd.incref()
- defer fd.decref()
- if fd.sysfd == syscall.InvalidHandle {
- return 0, os.EINVAL
+ if err := fd.incref(false); err != nil {
+ return 0, err
}
+ defer fd.decref()
var o writeOp
o.Init(fd, buf, 'w')
return iosrv.ExecIO(&o, fd.wdeadline)
}
fd.wio.Lock()
defer fd.wio.Unlock()
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
if fd.sysfd == syscall.InvalidHandle {
return 0, os.EINVAL
}
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
- if fd == nil || fd.sysfd == syscall.InvalidHandle {
- return nil, os.EINVAL
+ if err := fd.incref(false); err != nil {
+ return 0, err
}
- fd.incref()
defer fd.decref()
// Get new socket.
"regexp"
"runtime"
"testing"
+ "time"
)
var runErrorTest = flag.Bool("run_error_test", false, "let TestDialError check for dns errors")
t.Errorf("read = %q, want \"response\"", got)
}
}
+
+func TestTCPListenClose(t *testing.T) {
+ l, err := Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("Listen failed: %v", err)
+ }
+
+ done := make(chan bool, 1)
+ go func() {
+ time.Sleep(100 * time.Millisecond)
+ l.Close()
+ }()
+ go func() {
+ _, err = l.Accept()
+ if err == nil {
+ t.Error("Accept succeeded")
+ } else {
+ t.Logf("Accept timeout error: %s (any error is fine)", err)
+ }
+ done <- true
+ }()
+ select {
+ case <-done:
+ case <-time.After(2 * time.Second):
+ t.Fatal("timeout waiting for TCP close")
+ }
+}
+
+func TestUDPListenClose(t *testing.T) {
+ l, err := ListenPacket("udp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("Listen failed: %v", err)
+ }
+
+ buf := make([]byte, 1000)
+ done := make(chan bool, 1)
+ go func() {
+ time.Sleep(100 * time.Millisecond)
+ l.Close()
+ }()
+ go func() {
+ _, _, err = l.ReadFrom(buf)
+ if err == nil {
+ t.Error("ReadFrom succeeded")
+ } else {
+ t.Logf("ReadFrom timeout error: %s (any error is fine)", err)
+ }
+ done <- true
+ }()
+ select {
+ case <-done:
+ case <-time.After(2 * time.Second):
+ t.Fatal("timeout waiting for UDP close")
+ }
+}
c.wio.Lock()
defer c.wio.Unlock()
- c.incref()
+ if err := c.incref(false); err != nil {
+ return 0, err, true
+ }
defer c.decref()
dst := c.sysfd
break
}
if err1 == syscall.EAGAIN && c.wdeadline >= 0 {
- pollserver.WaitWrite(c)
- continue
+ if err1 = pollserver.WaitWrite(c); err1 == nil {
+ continue
+ }
}
if err1 != nil {
// This includes syscall.ENOSYS (no kernel
c.wio.Lock()
defer c.wio.Unlock()
- c.incref()
+ if err := c.incref(); err != nil {
+ return 0, err, true
+ }
defer c.decref()
var o sendfileOp
}
// Send explicit ending for unixpacket.
- // Older Linux kernels do stop reads on close.
+ // Older Linux kernels do not stop reads on close.
if network == "unixpacket" {
fd.Write([]byte("END"))
}
}
func setReadBuffer(fd *netFD, bytes int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes))
}
func setWriteBuffer(fd *netFD, bytes int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
}
}
func setReuseAddr(fd *netFD, reuse bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse)))
}
func setDontRoute(fd *netFD, dontroute bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute)))
}
func setKeepAlive(fd *netFD, keepalive bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
}
func setNoDelay(fd *netFD, noDelay bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
}
l.Onoff = 0
l.Linger = 0
}
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))
}
)
func ipv4TOS(fd *netFD) (int, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS)
if err != nil {
- return -1, os.NewSyscallError("getsockopt", err)
+ return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv4TOS(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TOS, v)
if err != nil {
}
func ipv4TTL(fd *netFD) (int, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL)
if err != nil {
- return -1, os.NewSyscallError("getsockopt", err)
+ return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv4TTL(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_TTL, v)
if err != nil {
if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
return err
}
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
}
if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
return err
}
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
}
func ipv6HopLimit(fd *netFD) (int, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS)
if err != nil {
- return -1, os.NewSyscallError("getsockopt", err)
+ return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv6HopLimit(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, v)
if err != nil {
}
func ipv6MulticastInterface(fd *netFD) (*Interface, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return nil, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF)
if err != nil {
if ifi != nil {
v = ifi.Index
}
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
if err != nil {
}
func ipv6MulticastHopLimit(fd *netFD) (int, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS)
if err != nil {
- return -1, os.NewSyscallError("getsockopt", err)
+ return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv6MulticastHopLimit(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_HOPS, v)
if err != nil {
}
func ipv6MulticastLoopback(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP)
if err != nil {
}
func setIPv6MulticastLoopback(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
if err != nil {
if ifi != nil {
mreq.Interface = uint32(ifi.Index)
}
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
}
if ifi != nil {
mreq.Interface = uint32(ifi.Index)
}
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq))
}
)
func ipv4MulticastTTL(fd *netFD) (int, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
if err != nil {
- return -1, os.NewSyscallError("getsockopt", err)
+ return 0, os.NewSyscallError("getsockopt", err)
}
return int(v), nil
}
func setIPv4MulticastTTL(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, byte(v))
if err != nil {
}
func ipv6TrafficClass(fd *netFD) (int, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
if err != nil {
- return -1, os.NewSyscallError("getsockopt", err)
+ return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv6TrafficClass(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
if err != nil {
)
func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return nil, err
+ }
defer fd.decref()
a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
if err != nil {
}
var x [4]byte
copy(x[:], ip.To4())
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
if err != nil {
}
func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
if err != nil {
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
if err != nil {
}
func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
if err != nil {
}
func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
if err != nil {
)
func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return nil, err
+ }
defer fd.decref()
mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
if err != nil {
v = int32(ifi.Index)
}
mreq := &syscall.IPMreqn{Ifindex: v}
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
if err != nil {
}
func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
if err != nil {
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
if err != nil {
}
func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
if err != nil {
}
func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
if err != nil {
)
func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return nil, err
+ }
defer fd.decref()
mreq, err := syscall.GetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
if err != nil {
v = int32(ifi.Index)
}
mreq := &syscall.IPMreqn{Ifindex: v}
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
if err != nil {
}
func ipv4MulticastTTL(fd *netFD) (int, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL)
if err != nil {
}
func setIPv4MulticastTTL(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
if err != nil {
}
func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
if err != nil {
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
if err != nil {
}
func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO)
if err != nil {
}
func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_PKTINFO, boolint(v))
if err != nil {
}
func ipv6TrafficClass(fd *netFD) (int, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return 0, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS)
if err != nil {
- return -1, os.NewSyscallError("getsockopt", err)
+ return 0, os.NewSyscallError("getsockopt", err)
}
return v, nil
}
func setIPv6TrafficClass(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, v)
if err != nil {
)
func ipv4MulticastInterface(fd *netFD) (*Interface, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return nil, err
+ }
defer fd.decref()
a, err := syscall.GetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF)
if err != nil {
}
var x [4]byte
copy(x[:], ip.To4())
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
if err != nil {
}
func ipv4MulticastLoopback(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP)
if err != nil {
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
if err != nil {
}
func ipv4ReceiveInterface(fd *netFD) (bool, error) {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return false, err
+ }
defer fd.decref()
v, err := syscall.GetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF)
if err != nil {
}
func setIPv4ReceiveInterface(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_RECVIF, boolint(v))
if err != nil {
}
var x [4]byte
copy(x[:], ip.To4())
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, x)
if err != nil {
}
func setIPv4MulticastTTL(fd *netFD, v int) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, v)
if err != nil {
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- fd.incref()
+ if err := fd.incref(false); err != nil {
+ return err
+ }
defer fd.decref()
err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
if err != nil {