Don't truncate rmw_time_t QoS durations in the override defaults - #3268
Don't truncate rmw_time_t QoS durations in the override defaults#3268Dev-next-gen wants to merge 2 commits into
Conversation
rclcpp::detail::rmw_duration_to_int64_t built an rclcpp::Duration from static_cast<int32_t>(rmw_duration.sec). RMW_DURATION_INFINITE, and the best-available deadline and liveliness lease sentinels, all carry 9223372036 seconds, so the cast wrapped and the helper returned 633437444854775807 ns instead of 9223372036854775807 ns. That value is what declare_qos_parameters() declares as the default for the deadline, lifespan and liveliness_lease_duration overrides, and it is fed straight back into the profile through apply_qos_override(). Enabling those overrides on a profile carrying an infinite duration therefore silently replaced it with a finite ~20 year duration, which changes QoS compatibility matching. Seconds values in [2^31, 2^32) wrap to a negative int32_t and produce a negative duration, which QoS::deadline() then rejects with "rmw_time_t cannot be negative". Use rclcpp::Duration::from_rmw_time(), which is the conversion the QoS getters already use and which saturates instead of wrapping. Signed-off-by: leoca <[email protected]>
fujitatomoya
left a comment
There was a problem hiding this comment.
I could not build the full ROS 2 stack here
why? can you take a look at https://docs.ros.org/en/rolling/Get-Started/Installation/Alternatives/Ubuntu-Development-Setup.html
IMO this looks good, but we are not going to approve that is NOT verified, we are not sure if this can be built without error.
|
and please use our pull request template. |
|
Thanks, that was a fair objection — I should not have opened it unverified. I built and tested it. Official With the change, which is the truncated value the description predicts. The other seven tests pass on both sides. Full output is in the updated description. I also rewrote the description using the ros2 template, including the Generative AI section. |
Signed-off-by: leoca <[email protected]>
df79610 to
ec6a61d
Compare
Description
rclcpp::detail::rmw_duration_to_int64_t()converts anrmw_time_tby hand:rmw_time_t::secis auint64_t, and the durations that matter here do not fit in anint32_t.RMW_DURATION_INFINITEis{9223372036, 854775807}, andRMW_QOS_DEADLINE_BEST_AVAILABLE/RMW_QOS_LIVELINESS_LEASE_DURATION_BEST_AVAILABLEare{9223372036, 854775806}. Casting9223372036toint32_twraps to633437444, so the helper returns633437444854775807ns where it should return9223372036854775807ns.declare_qos_parameters()uses that value twice: as the default for thedeadline,lifespanandliveliness_lease_durationoverride parameters, and then it feeds the declared value back into the profile throughapply_qos_override(). So enabling those overrides on a profile carrying an infinite duration silently turns it into a finite one of about 20 years, which is a different thing for QoS compatibility matching — a subscription requesting a 20 year deadline no longer matches a publisher offering an infinite one. Seconds in[2^31, 2^32)are worse: they wrap negative, produce a negativeDuration, andQoS::deadline()throwsrmw_time_t cannot be negative.rclcpp::Duration::from_rmw_time()already does this conversion correctly — it saturates atINT64_MAXinstead of wrapping — and it is what theQoS::deadline(),QoS::lifespan()andQoS::liveliness_lease_duration()getters use. This PR makes the helper use it too.For every
rmw_time_twhose seconds fit in anint32_tthe two expressions produce the same number, so nothing changes for ordinary durations. The function isinlineand lives inrclcpp::detail, so no public signature moves.Fixes # (no issue filed; found while reading the QoS override code)
Is this user-facing behavior change?
Yes, for one case that is currently broken. A QoS profile with an infinite
deadline,lifespanorliveliness_lease_durationkeeps that infinite value when the corresponding parameter override is declared, instead of being silently reduced to ~292 years... in practice633437444854775807ns, about 20 years. Profiles whose durations already fit in anint32_tnumber of seconds are unchanged.Did you use Generative AI?
Yes. Claude Opus 5, through Claude Code, found the truncation, wrote the one-line change in
qos_parameters.hpp, wrote thedeclare_infinite_durationstest intest_qos_parameters.cpp, and drafted this description. The build and test verification below was run afterwards and is reported exactly as the container printed it.Additional Information
Verification. My earlier note said I could not build the full ROS 2 stack. That is now done, in the official
ros:rolling-ros-baseimage with the test dependencies installed byrosdep. Environment: Ubuntu 26.04.1, ROS 2 Rolling, gcc 15.2.0, cmake 4.2.3. Base:e47c084onrolling.With this change applied,
colcon build --packages-select rclcppsucceeds and the test file passes:Then I reverted only
rclcpp/include/rclcpp/detail/qos_parameters.hpp, keeping the new test, rebuilt, and it fails on currentrolling:That is the truncated value predicted above, produced by the code as it stands today. The other seven tests in the file pass on both sides.