From 30863642468dd7386325edb036cc5fa0928abd6f Mon Sep 17 00:00:00 2001 From: JackDoan Date: Fri, 30 Jan 2026 14:48:56 -0600 Subject: [PATCH] block less I guess --- interface.go | 12 ++++++---- overlay/tun_linux.go | 55 +++++++++++++++++++++++--------------------- udp/udp_linux.go | 10 ++++---- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/interface.go b/interface.go index fd80cc87..332a7f98 100644 --- a/interface.go +++ b/interface.go @@ -507,12 +507,14 @@ func (f *Interface) Close() error { } // Release the tun readers - for i, u := range f.readers { - err := u.Close() - if err != nil { - f.l.WithError(err).WithField("i", i).Error("Error while closing tun device") + for i, r := range f.readers { + if i == 0 { + continue // f.readers[0] is f.inside, which we want to save for last, since it closes other stuff too + } + if err := r.Close(); err != nil { + f.l.WithError(err).Error("Error while closing tun reader") } } - return nil + return f.inside.Close() } diff --git a/overlay/tun_linux.go b/overlay/tun_linux.go index 7e4aa418..aa5bb42a 100644 --- a/overlay/tun_linux.go +++ b/overlay/tun_linux.go @@ -72,6 +72,11 @@ type ifreqQLEN struct { } func newTunFromFd(c *config.C, l *logrus.Logger, deviceFd int, vpnNetworks []netip.Prefix) (*tun, error) { + err := unix.SetNonblock(deviceFd, true) + if err != nil { + return nil, err + } + file := os.NewFile(uintptr(deviceFd), "/dev/net/tun") t, err := newTunGeneric(c, l, file, vpnNetworks) @@ -122,6 +127,11 @@ func newTun(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, multiqueu } name := strings.Trim(string(req.Name[:]), "\x00") + err = unix.SetNonblock(fd, true) + if err != nil { + return nil, err + } + file := os.NewFile(uintptr(fd), "/dev/net/tun") t, err := newTunGeneric(c, l, file, vpnNetworks) if err != nil { @@ -145,7 +155,12 @@ func newTunGeneric(c *config.C, l *logrus.Logger, file *os.File, vpnNetworks []n l: l, } - err := t.reload(c, true) + err := unix.SetNonblock(t.fd, true) + if err != nil { + return nil, err + } + + err = t.reload(c, true) if err != nil { return nil, err } @@ -251,6 +266,11 @@ func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) { return nil, err } + err = unix.SetNonblock(fd, true) + if err != nil { + return nil, err + } + file := os.NewFile(uintptr(fd), "/dev/net/tun") return file, nil @@ -261,29 +281,6 @@ func (t *tun) RoutesFor(ip netip.Addr) routing.Gateways { return r } -func (t *tun) Write(b []byte) (int, error) { - var nn int - maximum := len(b) - - for { - n, err := unix.Write(t.fd, b[nn:maximum]) - if n > 0 { - nn += n - } - if nn == len(b) { - return nn, err - } - - if err != nil { - return nn, err - } - - if n == 0 { - return nn, io.ErrUnexpectedEOF - } - } -} - func (t *tun) deviceBytes() (o [16]byte) { for i, c := range t.Device { o[i] = byte(c) @@ -712,11 +709,17 @@ func (t *tun) Close() error { } if t.ReadWriteCloser != nil { - _ = t.ReadWriteCloser.Close() + err := t.ReadWriteCloser.Close() + if err != nil { + t.l.WithField("error", err).Error("Failed to close read/write connection") + } } if t.ioctlFd > 0 { - _ = os.NewFile(t.ioctlFd, "ioctlFd").Close() + err := os.NewFile(t.ioctlFd, "ioctlFd").Close() + if err != nil { + t.l.WithField("error", err).Error("Failed to close ioctl fd") + } t.ioctlFd = 0 } diff --git a/udp/udp_linux.go b/udp/udp_linux.go index 1e7aa98d..8782f185 100644 --- a/udp/udp_linux.go +++ b/udp/udp_linux.go @@ -162,7 +162,7 @@ func (u *StdConn) ReadSingle(msgs []rawMessage) (int, error) { ) if err != 0 { - if err == unix.EAGAIN || err == unix.EINTR { + if err == unix.EAGAIN || err == unix.EINTR || err == unix.EWOULDBLOCK { continue } return 0, &net.OpError{Op: "recvmsg", Err: err} @@ -184,12 +184,12 @@ func (u *StdConn) ReadMulti(msgs []rawMessage) (int, error) { 0, 0, ) - if err == unix.EAGAIN || err == unix.EINTR { - if n == 0 { - continue - } else { + if err == unix.EAGAIN || err == unix.EINTR || err == unix.EWOULDBLOCK { + if int64(n) > 0 { //ran out of time, but have some messages to return return int(n), nil + } else { + continue } } else if err != 0 { return 0, &net.OpError{Op: "recvmmsg", Err: err}