fix(netwatch): drain AF_ROUTE socket to avoid macOS route monitor stall#165
Merged
Merged
Conversation
4 tasks
74a39df to
0c744fe
Compare
flub
requested changes
Jun 16, 2026
flub
left a comment
Contributor
There was a problem hiding this comment.
Nice, this is looking good! Mostly some nits, thanks for finding this bug!
The BSD/macOS route monitor read the AF_ROUTE socket with one AsyncRead::read per await and never drained. On an edge-triggered reactor that can drop the next readiness notification, so under sustained route churn the reader stalled with data still queued and stopped delivering NetworkMessage::Change for the rest of the process. Read via readable() + try_read() drained to WouldBlock instead. The UnixStream and its construction are unchanged.
0c744fe to
bb19855
Compare
Contributor
Author
|
Thanks for the quick review! Addressed all your comments. |
flub
approved these changes
Jun 16, 2026
flub
left a comment
Contributor
There was a problem hiding this comment.
Thanks!
(And please use the small "re-request review" button on github, it makes notifications a bit easier to handle on the reviewer-side. It is hidden under the "reviewers" menu to the right of each reviewer and only shows up when you have un-reviewed changed - not the best UX!)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes a read stall in the BSD/macOS route monitor.
netwatch/src/netmon/bsd.rsreads theAF_ROUTEsocket through atokio::net::UnixStreamwith oneAsyncRead::readper await, reading a single message per wakeup and never draining. On BSD/macOS the fd is registered edge-triggered, so leaving data queued can drop the next readiness notification: the reader then stalls with data still queued in the socket (FIONREAD > 0,pollreports it readable) and stops deliveringNetworkMessage::Change. The loop only recreates the socket on a read error, and the stall surfaces no error, so it does not recover.This drain-until-
WouldBlockrequirement is the documented contract of mio: mio'sPollsays an operation "must be performed repeatedly until it returnsWouldBlock", else "there is no guarantee that another readiness event will be delivered, even if further data is received".Changes:
readable()+try_read()drained toWouldBlockon each wakeup, instead of oneAsyncRead::readper await. TheUnixStreamand its construction are unchanged.parse_ribfiltering, and socket recreation with exponential backoff.read_availabledrains all queued messages in one readiness episode (via anAF_UNIXdatagram socketpair).Verified on macOS: under sustained route churn the old one-read-per-await reader stalls with data queued and the OS still reporting its socket readable, while the drain-to-
WouldBlockreader keeps its socket empty.Breaking Changes
None.
Notes & open questions
None.
Change checklist