Skip to content

Commit

Permalink
Eliminate busy loop when receiving messages from non-blocking socket
Browse files Browse the repository at this point in the history
For a non-blocking socket, it should wait for events first before
receiving messages from the socket, otherwise it would receive empty
message and run into a busy loop.

Signed-off-by: Quan Tian <[email protected]>
  • Loading branch information
tnqn committed May 23, 2024
1 parent 856e190 commit 05294ba
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions nl/nl_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,9 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
}

type NetlinkSocket struct {
fd int32
fd int32
// pfd is non nil when the socket is in non-blocking mode, and is used to wait for events on the socket.
pfd *unix.PollFd
lsa unix.SockaddrNetlink
sync.Mutex
}
Expand Down Expand Up @@ -728,17 +730,20 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
return nil, err
}

var pfd *unix.PollFd
// Sometimes (socket_linux.go:SocketGet), Subscribe is used to create a socket
// that subscirbed to no groups. So we don't need to set nonblock there.
// that subscribes to no groups. So we don't need to set nonblock there.
if len(groups) > 0 {
if err := unix.SetNonblock(fd, true); err != nil {
unix.Close(fd)
return nil, err
}
pfd = &unix.PollFd{Fd: int32(fd), Events: unix.POLLIN}
}

s := &NetlinkSocket{
fd: int32(fd),
fd: int32(fd),
pfd: pfd,
}
s.lsa.Family = unix.AF_NETLINK

Expand Down Expand Up @@ -791,6 +796,13 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetli
if fd < 0 {
return nil, nil, fmt.Errorf("Receive called on a closed socket")
}
// The socket is in non-blocking mode.
if s.pfd != nil {
if _, err := unix.Poll([]unix.PollFd{*s.pfd}, -1); err != nil {
return nil, nil, fmt.Errorf("Error polling the socket: %w", err)
}
}

var fromAddr *unix.SockaddrNetlink
var rb [RECEIVE_BUFFER_SIZE]byte
nr, from, err := unix.Recvfrom(fd, rb[:], 0)
Expand Down

0 comments on commit 05294ba

Please sign in to comment.