Skip to content

Instantly share code, notes, and snippets.

@lithdew
Last active February 24, 2024 01:02
Show Gist options
  • Save lithdew/b647641c8d6acea54c59aebb75f11abc to your computer and use it in GitHub Desktop.
Save lithdew/b647641c8d6acea54c59aebb75f11abc to your computer and use it in GitHub Desktop.
Differences between Linux and Mac for sockets.
  1. A listening socket blocked on accept() can be unblocked by calling shutdown(socket_fd, SHUT_RD) on Linux. On Mac, calling shutdown(socket_fd, SHUT_RD) on a listening socket that is blocked on accept() will return an error ENOTCONN. To unblock a listening socket blocked on accept() on Mac requires calling close(socket_fd), which will cause the blocking accept() call to return an error EBADF.

Therefore, in order to unblock a socket on accept() on both Mac/Linux, shutdown() should not be relied on. Rather, an async cancellation scheme (such as cancellation tokens in .NET) should be used instead to unblock the call to accept().

  1. When a socket is instantiated and subsequently registered to epoll, or when a socket is shut down (via. shutdown() or setsockopt(SO_LINGER)) on Linux, epoll will be notified with EPOLLHUP on the socket. On Mac, kqueue will only notify when a socket is shut down (via. shutdown() or setsockopt(SO_LINGER)) by sending a EV_EOF notification on filters EVFILT_READ, and EVFILT_WRITE.

This is important when it comes to managing resources throughout the lifecycle of a socket.

On Linux, any resources owned by a socket should only be fully cleaned up when an epoll notification is received that either the socket's read or write sides has been fully hung up (read or write side active -> EPOLLHUP w/o EPOLLIN or EPOLLOUT). Otherwise, a use-after-free may occur where epoll notifications are still sent and attempted to be handled by a socket in spite of the socket's resources having already been cleaned up.

On Mac, any resources owned by a socket should only be fully cleaned up when kqueue notifications are received that either the socket's read or write sides has been fully hung up (read or write side active -> EVFILT_READ and EVFILT_WRITE w/ EV_EOF). Otherwise, a use-after-free may occur where kqueue notifications are still sent and attempted to be handled by the socket in spite of the socket's resources having already been cleaned up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment