fix(rmw_wait): deliver TRANSIENT_LOCAL latched samples to late joiners of idle publishers - #37
Merged
Conversation
…s of idle publishers An idle publisher's executor blocks in rmw_wait with an infinite timeout, and a subscriber joining only bumps the shared-memory generation counter (no fd fires), so the top-of-wait late-joiner replay never re-runs and the retained sample is never delivered. Cap the wait at 200 ms so the executor loops and re-checks the graph. The cap only shortens the caller's timeout (a non-blocking 0 stays 0), and an early return with nothing ready is already part of the rmw_wait contract. Add a regression test that reproduces the ordering (subscriber joins after the executor is already blocked in rmw_wait).
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.
Problem
A
TRANSIENT_LOCAL(latched) publisher on an otherwise idle node blocks inrmw_waitwith an infinite timeout. A subscriber joining later only bumps the shared-memory generation counter, which signals no file descriptor — so the top-of-wait late-joiner replay never re-runs and the late subscriber never receives the retained sample.The existing
TransientLocalReplayOnWait*tests don't catch this: they create the subscriber before callingrmw_wait, whereas the real failure needs the executor to be already blocked when the subscriber joins.Fix
Cap the wait timeout at 200 ms in
rmw_waitso the executor loops and re-checks the graph. It only ever shortens the caller's timeout (a non-blocking0stays0), and returning early with nothing ready is already part of thermw_waitcontract — callers simply re-wait.Test
Adds
TransientLocalReplayReachesLateJoinerWhileWaitBlocked: the subscriber joins after the executor is already blocked inrmw_wait; a guard condition cleanly unblocks the thread on teardown so the test never hangs. Fails before the fix, passes after.Verification
Full suite green on Jazzy — every
test_rmw_*suite passes, including the 21test_rmw_qostests and the timing-sensitivetest_rmw_wait.