addr: add receive timeout option for AddrSubscribe

Otherwise addrSubscribeAt()'s goroutine will block in s.Receive()
and potentially call callbacks long after the done channel has
been closed by the caller.

Signed-off-by: Dan Williams <dcbw@redhat.com>
This commit is contained in:
Dan Williams 2022-03-04 15:19:46 -06:00 committed by Vish (Ishaya) Abrams
parent b112db377d
commit 083e92e21e

View File

@ -296,13 +296,13 @@ type AddrUpdate struct {
// AddrSubscribe takes a chan down which notifications will be sent
// when addresses change. Close the 'done' chan to stop subscription.
func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error {
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0)
return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil)
}
// AddrSubscribeAt works like AddrSubscribe plus it allows the caller
// to choose the network namespace in which to subscribe (ns).
func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error {
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0)
return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil)
}
// AddrSubscribeOptions contains a set of options to use with
@ -312,6 +312,7 @@ type AddrSubscribeOptions struct {
ErrorCallback func(error)
ListExisting bool
ReceiveBufferSize int
ReceiveTimeout *unix.Timeval
}
// AddrSubscribeWithOptions work like AddrSubscribe but enable to
@ -322,14 +323,20 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option
none := netns.None()
options.Namespace = &none
}
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize)
return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize, options.ReceiveTimeout)
}
func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int) error {
func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int, rcvTimeout *unix.Timeval) error {
s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR)
if err != nil {
return err
}
if rcvTimeout != nil {
if err := s.SetReceiveTimeout(rcvTimeout); err != nil {
return err
}
}
if done != nil {
go func() {
<-done