Skip to content

fix: normalize ENOTSOCK/EBADF to os.ErrClosed on macOS TUN close#11

Open
Eninspace wants to merge 1 commit intoMetaCubeX:metafrom
Eninspace:fix/darwin-tun-close-errno
Open

fix: normalize ENOTSOCK/EBADF to os.ErrClosed on macOS TUN close#11
Eninspace wants to merge 1 commit intoMetaCubeX:metafrom
Eninspace:fix/darwin-tun-close-errno

Conversation

@Eninspace
Copy link
Copy Markdown

Problem

On macOS, closing a utun device while batch reader/writer goroutines are active causes recvmsg_x/sendmsg_x/writev to return ENOTSOCK or EBADF (depending on timing). These are not recognized by E.IsClosed(), causing error spam in logs:

level=error msg="batch read packet: socket operation on non-socket"
level=error msg="batch read packet: bad file descriptor"

Root cause

macOS utun is a socket (socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL)), unlike Linux TUN which is a file (/dev/net/tun). When the utun fd is closed, the errno values differ:

Platform TUN type Errno on close
Linux File EBADFD (already handled in tun_linux.go:90,248)
macOS Socket ENOTSOCK + EBADF (not handled)

Fix

Normalize ENOTSOCK and EBADF to os.ErrClosed in tun_darwin.go, same pattern as EBADFD handling in tun_linux.go.

3 locations (all places that return raw errno from utun syscalls):

  1. BatchRead()BlockingRecvMMsgUntilStopped
  2. BatchWrite() non-MsgX path — NonBlockingWriteIovec
  3. BatchWrite() MsgX path — NonBlockingSendMMsg

Changes

  • 1 file changed: tun_darwin.go
  • Added "errors" import
  • 10 lines added (3 error checks, same pattern as Linux)

On macOS, closing a utun device while batch reader/writer goroutines
are active causes recvmsg_x/sendmsg_x/writev to return ENOTSOCK or
EBADF (depending on timing). These are not recognized by E.IsClosed(),
causing error spam in logs ("batch read packet: socket operation on
non-socket" / "batch read packet: bad file descriptor").

This normalizes both errors to os.ErrClosed at the source, following
the same pattern already used for EBADFD on Linux (tun_linux.go:90,248).

macOS utun is a socket (PF_SYSTEM), unlike Linux TUN which is a file
(/dev/net/tun), so the errno values differ:
- Linux:  EBADFD (file descriptor in bad state)
- macOS:  ENOTSOCK (socket op on non-socket) + EBADF (bad fd)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant